diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-07-25 16:12:27 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-07-25 16:12:27 +0100 |
| commit | e89dbc142f5a0a517f197562f5f228681d9aed47 (patch) | |
| tree | 521dbec8d259f7c982345b40bb128a21795a2012 /src/bin/ngit/sub_commands | |
| parent | 419b827f7c0d826f5eedf574bce0cf9b85cab4ca (diff) | |
| parent | 0cad465dd3f78bd6c680067d12d396d4782829bf (diff) | |
Merge branch 'add-PR-feature-to-remote'
Diffstat (limited to 'src/bin/ngit/sub_commands')
| -rw-r--r-- | src/bin/ngit/sub_commands/init.rs | 16 | ||||
| -rw-r--r-- | src/bin/ngit/sub_commands/list.rs | 211 |
2 files changed, 145 insertions, 82 deletions
diff --git a/src/bin/ngit/sub_commands/init.rs b/src/bin/ngit/sub_commands/init.rs index 1242e45..eaaf83d 100644 --- a/src/bin/ngit/sub_commands/init.rs +++ b/src/bin/ngit/sub_commands/init.rs | |||
| @@ -229,7 +229,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 229 | .map(std::string::ToString::to_string) | 229 | .map(std::string::ToString::to_string) |
| 230 | .collect::<Vec<String>>() | 230 | .collect::<Vec<String>>() |
| 231 | } else { | 231 | } else { |
| 232 | client.get_fallback_relays().clone() | 232 | client.get_relay_default_set().clone() |
| 233 | } | 233 | } |
| 234 | } else { | 234 | } else { |
| 235 | args.relays.clone() | 235 | args.relays.clone() |
| @@ -252,14 +252,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 252 | args.blossoms.clone() | 252 | args.blossoms.clone() |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | let fallback_grasp_servers = | 255 | let fallback_grasp_servers = client.get_grasp_default_set(); |
| 256 | if let Ok(Some(s)) = git_repo.get_git_config_item("nostr.grasp-default-set", None) { | ||
| 257 | s.split(';') | ||
| 258 | .filter_map(|url| normalize_grasp_server_url(url).ok()) // Attempt to parse and filter out errors | ||
| 259 | .collect() | ||
| 260 | } else { | ||
| 261 | vec!["relay.ngit.dev".to_string(), "gitnostr.com".to_string()] | ||
| 262 | }; | ||
| 263 | 256 | ||
| 264 | let selected_grasp_servers = if has_server_and_relay_flags { | 257 | let selected_grasp_servers = if has_server_and_relay_flags { |
| 265 | // ignore so a script running `ngit init` can contiue without prompts | 258 | // ignore so a script running `ngit init` can contiue without prompts |
| @@ -269,14 +262,13 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 269 | repo_ref.as_ref(), | 262 | repo_ref.as_ref(), |
| 270 | &args.relays, | 263 | &args.relays, |
| 271 | &args.clone_url, | 264 | &args.clone_url, |
| 272 | &args.blossoms, | ||
| 273 | &identifier, | 265 | &identifier, |
| 274 | ); | 266 | ); |
| 275 | let mut selections: Vec<bool> = vec![true; options.len()]; // Initialize selections based on existing options | 267 | let mut selections: Vec<bool> = vec![true; options.len()]; // Initialize selections based on existing options |
| 276 | let empty = options.is_empty(); | 268 | let empty = options.is_empty(); |
| 277 | for fallback in fallback_grasp_servers { | 269 | for fallback in fallback_grasp_servers { |
| 278 | // Check if any option contains the fallback as a substring | 270 | // Check if any option contains the fallback as a substring |
| 279 | if !options.iter().any(|option| option.contains(&fallback)) { | 271 | if !options.iter().any(|option| option.contains(fallback)) { |
| 280 | options.push(fallback.clone()); // Add fallback if not found | 272 | options.push(fallback.clone()); // Add fallback if not found |
| 281 | selections.push(empty); // mark as selected if no existing ngit relay otherwise not | 273 | selections.push(empty); // mark as selected if no existing ngit relay otherwise not |
| 282 | } | 274 | } |
| @@ -464,7 +456,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 464 | let mut selections: Vec<bool> = vec![true; options.len()]; | 456 | let mut selections: Vec<bool> = vec![true; options.len()]; |
| 465 | 457 | ||
| 466 | // add fallback relays as options | 458 | // add fallback relays as options |
| 467 | for relay in client.get_fallback_relays().clone() { | 459 | for relay in client.get_relay_default_set().clone() { |
| 468 | if !options.iter().any(|r| r.contains(&relay)) | 460 | if !options.iter().any(|r| r.contains(&relay)) |
| 469 | && !formatted_selected_grasp_servers | 461 | && !formatted_selected_grasp_servers |
| 470 | .iter() | 462 | .iter() |
diff --git a/src/bin/ngit/sub_commands/list.rs b/src/bin/ngit/sub_commands/list.rs index 0330be1..0083c91 100644 --- a/src/bin/ngit/sub_commands/list.rs +++ b/src/bin/ngit/sub_commands/list.rs | |||
| @@ -3,10 +3,12 @@ use std::{io::Write, ops::Add}; | |||
| 3 | use anyhow::{Context, Result, bail}; | 3 | use anyhow::{Context, Result, bail}; |
| 4 | use ngit::{ | 4 | use ngit::{ |
| 5 | client::{ | 5 | client::{ |
| 6 | Params, get_all_proposal_patch_events_from_cache, get_proposals_and_revisions_from_cache, | 6 | Params, get_all_proposal_patch_pr_pr_update_events_from_cache, |
| 7 | get_proposals_and_revisions_from_cache, | ||
| 7 | }, | 8 | }, |
| 8 | git_events::{ | 9 | git_events::{ |
| 9 | get_commit_id_from_patch, get_most_recent_patch_with_ancestors, status_kinds, tag_value, | 10 | KIND_PULL_REQUEST, KIND_PULL_REQUEST_UPDATE, get_commit_id_from_patch, |
| 11 | get_pr_tip_event_or_most_recent_patch_with_ancestors, get_status, status_kinds, tag_value, | ||
| 10 | }, | 12 | }, |
| 11 | }; | 13 | }; |
| 12 | use nostr_sdk::Kind; | 14 | use nostr_sdk::Kind; |
| @@ -70,26 +72,15 @@ pub async fn launch() -> Result<()> { | |||
| 70 | 72 | ||
| 71 | let proposals: Vec<nostr::Event> = proposals_and_revisions | 73 | let proposals: Vec<nostr::Event> = proposals_and_revisions |
| 72 | .iter() | 74 | .iter() |
| 73 | .filter(|e| !event_is_revision_root(e)) | 75 | .filter(|e| |
| 76 | // If we wanted to treat to list Pull Requests that revise a Patch we would do this: | ||
| 77 | // e.kind.eq(&KIND_PULL_REQUEST) || | ||
| 78 | !event_is_revision_root(e)) | ||
| 74 | .cloned() | 79 | .cloned() |
| 75 | .collect(); | 80 | .collect(); |
| 76 | 81 | ||
| 77 | for proposal in &proposals { | 82 | for proposal in &proposals { |
| 78 | let status = if let Some(e) = statuses | 83 | let status = get_status(proposal, &repo_ref, &statuses, &proposals); |
| 79 | .iter() | ||
| 80 | .filter(|e| { | ||
| 81 | status_kinds().contains(&e.kind) | ||
| 82 | && e.tags.iter().any(|t| { | ||
| 83 | t.as_slice().len() > 1 && t.as_slice()[1].eq(&proposal.id.to_string()) | ||
| 84 | }) | ||
| 85 | }) | ||
| 86 | .collect::<Vec<&nostr::Event>>() | ||
| 87 | .first() | ||
| 88 | { | ||
| 89 | e.kind | ||
| 90 | } else { | ||
| 91 | Kind::GitStatusOpen | ||
| 92 | }; | ||
| 93 | if status.eq(&Kind::GitStatusOpen) { | 84 | if status.eq(&Kind::GitStatusOpen) { |
| 94 | open_proposals.push(proposal); | 85 | open_proposals.push(proposal); |
| 95 | } else if status.eq(&Kind::GitStatusClosed) { | 86 | } else if status.eq(&Kind::GitStatusClosed) { |
| @@ -184,21 +175,22 @@ pub async fn launch() -> Result<()> { | |||
| 184 | let cover_letter = event_to_cover_letter(proposals_for_status[selected_index]) | 175 | let cover_letter = event_to_cover_letter(proposals_for_status[selected_index]) |
| 185 | .context("failed to extract proposal details from proposal root event")?; | 176 | .context("failed to extract proposal details from proposal root event")?; |
| 186 | 177 | ||
| 187 | let commits_events: Vec<nostr::Event> = get_all_proposal_patch_events_from_cache( | 178 | let commits_events: Vec<nostr::Event> = |
| 188 | git_repo_path, | 179 | get_all_proposal_patch_pr_pr_update_events_from_cache( |
| 189 | &repo_ref, | 180 | git_repo_path, |
| 190 | &proposals_for_status[selected_index].id, | 181 | &repo_ref, |
| 191 | ) | 182 | &proposals_for_status[selected_index].id, |
| 192 | .await?; | 183 | ) |
| 184 | .await?; | ||
| 193 | 185 | ||
| 194 | let Ok(most_recent_proposal_patch_chain) = | 186 | let Ok(most_recent_proposal_patch_chain_or_pr_or_pr_update) = |
| 195 | get_most_recent_patch_with_ancestors(commits_events.clone()) | 187 | get_pr_tip_event_or_most_recent_patch_with_ancestors(commits_events.clone()) |
| 196 | else { | 188 | else { |
| 197 | if Interactor::default().confirm( | 189 | if Interactor::default().confirm( |
| 198 | PromptConfirmParms::default() | 190 | PromptConfirmParms::default() |
| 199 | .with_default(true) | 191 | .with_default(true) |
| 200 | .with_prompt( | 192 | .with_prompt( |
| 201 | "failed to find any patches on this proposal. choose another proposal?", | 193 | "failed to find any PR or patch events on this proposal. choose another proposal?", |
| 202 | ), | 194 | ), |
| 203 | )? { | 195 | )? { |
| 204 | continue; | 196 | continue; |
| @@ -208,15 +200,60 @@ pub async fn launch() -> Result<()> { | |||
| 208 | // for commit in &most_recent_proposal_patch_chain { | 200 | // for commit in &most_recent_proposal_patch_chain { |
| 209 | // println!("recent_event: {:?}", commit.as_json()); | 201 | // println!("recent_event: {:?}", commit.as_json()); |
| 210 | // } | 202 | // } |
| 203 | if most_recent_proposal_patch_chain_or_pr_or_pr_update | ||
| 204 | .iter() | ||
| 205 | .any(|e| [KIND_PULL_REQUEST, KIND_PULL_REQUEST_UPDATE].contains(&e.kind)) | ||
| 206 | { | ||
| 207 | match Interactor::default().choice( | ||
| 208 | PromptChoiceParms::default() | ||
| 209 | .with_prompt( | ||
| 210 | "this is new PR event kind which isn't supported in `ngit list` yet", | ||
| 211 | ) | ||
| 212 | .with_default(0) | ||
| 213 | .with_choices( | ||
| 214 | if [Kind::GitStatusOpen, Kind::GitStatusDraft].contains(&selected_status) | ||
| 215 | && git_repo | ||
| 216 | .get_first_nostr_remote_when_in_ngit_binary() | ||
| 217 | .await | ||
| 218 | .is_ok_and(|r| r.is_some()) | ||
| 219 | { | ||
| 220 | vec![ | ||
| 221 | format!( | ||
| 222 | "I'll manually checkout the proposal at remote branch '{}'", | ||
| 223 | cover_letter | ||
| 224 | .get_branch_name_with_pr_prefix_and_shorthand_id() | ||
| 225 | .unwrap() | ||
| 226 | ), | ||
| 227 | // TODO fetch oids and follow similar logic for dealing with | ||
| 228 | // conflcts as with patches below | ||
| 229 | "back to proposals".to_string(), | ||
| 230 | ] | ||
| 231 | } else { | ||
| 232 | vec!["back to proposals".to_string()] | ||
| 233 | }, | ||
| 234 | ), | ||
| 235 | )? { | ||
| 236 | 0 => continue, | ||
| 237 | _ => { | ||
| 238 | bail!("unexpected choice") | ||
| 239 | } | ||
| 240 | }; | ||
| 241 | } | ||
| 211 | 242 | ||
| 212 | let binding_patch_text_ref = format!("{} commits", most_recent_proposal_patch_chain.len()); | 243 | let binding_patch_text_ref = format!( |
| 213 | let patch_text_ref = if most_recent_proposal_patch_chain.len().gt(&1) { | 244 | "{} commits", |
| 245 | most_recent_proposal_patch_chain_or_pr_or_pr_update.len() | ||
| 246 | ); | ||
| 247 | let patch_text_ref = if most_recent_proposal_patch_chain_or_pr_or_pr_update | ||
| 248 | .len() | ||
| 249 | .gt(&1) | ||
| 250 | { | ||
| 214 | binding_patch_text_ref.as_str() | 251 | binding_patch_text_ref.as_str() |
| 215 | } else { | 252 | } else { |
| 216 | "1 commit" | 253 | "1 commit" |
| 217 | }; | 254 | }; |
| 218 | 255 | ||
| 219 | let no_support_for_patches_as_branch = most_recent_proposal_patch_chain | 256 | let no_support_for_patches_as_branch = most_recent_proposal_patch_chain_or_pr_or_pr_update |
| 220 | .iter() | 257 | .iter() |
| 221 | .any(|event| !patch_supports_commit_ids(event)); | 258 | .any(|event| !patch_supports_commit_ids(event)); |
| 222 | 259 | ||
| @@ -226,16 +263,18 @@ pub async fn launch() -> Result<()> { | |||
| 226 | PromptChoiceParms::default() | 263 | PromptChoiceParms::default() |
| 227 | .with_default(0) | 264 | .with_default(0) |
| 228 | .with_choices(vec![ | 265 | .with_choices(vec![ |
| 229 | "learn why 'patch only' proposals can't be checked out".to_string(), | 266 | "learn why this proposals can't be checked out".to_string(), |
| 230 | format!("apply to current branch with `git am`"), | 267 | format!("apply to current branch with `git am`"), |
| 231 | format!("download to ./patches"), | 268 | format!("download to ./patches"), |
| 232 | "back".to_string(), | 269 | "back".to_string(), |
| 233 | ]), | 270 | ]), |
| 234 | )? { | 271 | )? { |
| 235 | 0 => { | 272 | 0 => { |
| 236 | println!("Some proposals are posted as 'patch only'\n"); | ||
| 237 | println!( | 273 | println!( |
| 238 | "they are not anchored against a particular state of the code base like a standard proposal or a GitHub Pull Request can be\n" | 274 | "Some proposals are posted as patch without listing a parent commit\n" |
| 275 | ); | ||
| 276 | println!( | ||
| 277 | "they are not anchored against a particular state of the code base like a standard patch or a pull request can be\n" | ||
| 239 | ); | 278 | ); |
| 240 | println!( | 279 | println!( |
| 241 | "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" | 280 | "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" |
| @@ -244,7 +283,7 @@ pub async fn launch() -> Result<()> { | |||
| 244 | "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" | 283 | "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" |
| 245 | ); | 284 | ); |
| 246 | println!( | 285 | println!( |
| 247 | "by default ngit posts proposals that support both the branch and patch model so either workflow can be used" | 286 | "by default ngit posts proposals with a parent commit so either workflow can be used" |
| 248 | ); | 287 | ); |
| 249 | Interactor::default().choice( | 288 | Interactor::default().choice( |
| 250 | PromptChoiceParms::default() | 289 | PromptChoiceParms::default() |
| @@ -253,8 +292,13 @@ pub async fn launch() -> Result<()> { | |||
| 253 | )?; | 292 | )?; |
| 254 | continue; | 293 | continue; |
| 255 | } | 294 | } |
| 256 | 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain), | 295 | 1 => { |
| 257 | 2 => save_patches_to_dir(most_recent_proposal_patch_chain, &git_repo), | 296 | launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update) |
| 297 | } | ||
| 298 | 2 => save_patches_to_dir( | ||
| 299 | most_recent_proposal_patch_chain_or_pr_or_pr_update, | ||
| 300 | &git_repo, | ||
| 301 | ), | ||
| 258 | 3 => continue, | 302 | 3 => continue, |
| 259 | _ => { | 303 | _ => { |
| 260 | bail!("unexpected choice") | 304 | bail!("unexpected choice") |
| @@ -277,9 +321,11 @@ pub async fn launch() -> Result<()> { | |||
| 277 | .eq(&cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?); | 321 | .eq(&cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?); |
| 278 | 322 | ||
| 279 | let proposal_base_commit = str_to_sha1(&tag_value( | 323 | let proposal_base_commit = str_to_sha1(&tag_value( |
| 280 | most_recent_proposal_patch_chain.last().context( | 324 | most_recent_proposal_patch_chain_or_pr_or_pr_update |
| 281 | "there should be at least one patch as we have already checked for this", | 325 | .last() |
| 282 | )?, | 326 | .context( |
| 327 | "there should be at least one patch as we have already checked for this", | ||
| 328 | )?, | ||
| 283 | "parent-commit", | 329 | "parent-commit", |
| 284 | )?) | 330 | )?) |
| 285 | .context("failed to get valid parent commit id from patch")?; | 331 | .context("failed to get valid parent commit id from patch")?; |
| @@ -300,8 +346,8 @@ pub async fn launch() -> Result<()> { | |||
| 300 | ], | 346 | ], |
| 301 | ))? { | 347 | ))? { |
| 302 | 0 | 3 => continue, | 348 | 0 | 3 => continue, |
| 303 | 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain), | 349 | 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update), |
| 304 | 2 => save_patches_to_dir(most_recent_proposal_patch_chain, &git_repo), | 350 | 2 => save_patches_to_dir(most_recent_proposal_patch_chain_or_pr_or_pr_update, &git_repo), |
| 305 | _ => { | 351 | _ => { |
| 306 | bail!("unexpected choice") | 352 | bail!("unexpected choice") |
| 307 | } | 353 | } |
| @@ -309,9 +355,13 @@ pub async fn launch() -> Result<()> { | |||
| 309 | } | 355 | } |
| 310 | 356 | ||
| 311 | let proposal_tip = str_to_sha1( | 357 | let proposal_tip = str_to_sha1( |
| 312 | &get_commit_id_from_patch(most_recent_proposal_patch_chain.first().context( | 358 | &get_commit_id_from_patch( |
| 313 | "there should be at least one patch as we have already checked for this", | 359 | most_recent_proposal_patch_chain_or_pr_or_pr_update |
| 314 | )?) | 360 | .first() |
| 361 | .context( | ||
| 362 | "there should be at least one patch as we have already checked for this", | ||
| 363 | )?, | ||
| 364 | ) | ||
| 315 | .context("failed to get valid commit_id from patch")?, | 365 | .context("failed to get valid commit_id from patch")?, |
| 316 | ) | 366 | ) |
| 317 | .context("failed to get valid commit_id from patch")?; | 367 | .context("failed to get valid commit_id from patch")?; |
| @@ -325,7 +375,7 @@ pub async fn launch() -> Result<()> { | |||
| 325 | .choice(PromptChoiceParms::default().with_default(0).with_choices(vec![ | 375 | .choice(PromptChoiceParms::default().with_default(0).with_choices(vec![ |
| 326 | format!( | 376 | format!( |
| 327 | "create and checkout proposal branch ({} ahead {} behind '{main_branch_name}')", | 377 | "create and checkout proposal branch ({} ahead {} behind '{main_branch_name}')", |
| 328 | most_recent_proposal_patch_chain.len(), | 378 | most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), |
| 329 | proposal_behind_main.len(), | 379 | proposal_behind_main.len(), |
| 330 | ), | 380 | ), |
| 331 | format!("apply to current branch with `git am`"), | 381 | format!("apply to current branch with `git am`"), |
| @@ -337,7 +387,7 @@ pub async fn launch() -> Result<()> { | |||
| 337 | let _ = git_repo | 387 | let _ = git_repo |
| 338 | .apply_patch_chain( | 388 | .apply_patch_chain( |
| 339 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, | 389 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, |
| 340 | most_recent_proposal_patch_chain, | 390 | most_recent_proposal_patch_chain_or_pr_or_pr_update, |
| 341 | ) | 391 | ) |
| 342 | .context("failed to apply patch chain")?; | 392 | .context("failed to apply patch chain")?; |
| 343 | 393 | ||
| @@ -347,8 +397,8 @@ pub async fn launch() -> Result<()> { | |||
| 347 | ); | 397 | ); |
| 348 | Ok(()) | 398 | Ok(()) |
| 349 | } | 399 | } |
| 350 | 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain), | 400 | 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update), |
| 351 | 2 => save_patches_to_dir(most_recent_proposal_patch_chain, &git_repo), | 401 | 2 => save_patches_to_dir(most_recent_proposal_patch_chain_or_pr_or_pr_update, &git_repo), |
| 352 | 3 => continue, | 402 | 3 => continue, |
| 353 | _ => { | 403 | _ => { |
| 354 | bail!("unexpected choice") | 404 | bail!("unexpected choice") |
| @@ -382,7 +432,7 @@ pub async fn launch() -> Result<()> { | |||
| 382 | .with_choices(vec![ | 432 | .with_choices(vec![ |
| 383 | format!( | 433 | format!( |
| 384 | "checkout proposal branch ({} ahead {} behind '{main_branch_name}')", | 434 | "checkout proposal branch ({} ahead {} behind '{main_branch_name}')", |
| 385 | most_recent_proposal_patch_chain.len(), | 435 | most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), |
| 386 | proposal_behind_main.len(), | 436 | proposal_behind_main.len(), |
| 387 | ), | 437 | ), |
| 388 | format!("apply to current branch with `git am`"), | 438 | format!("apply to current branch with `git am`"), |
| @@ -401,8 +451,13 @@ pub async fn launch() -> Result<()> { | |||
| 401 | ); | 451 | ); |
| 402 | Ok(()) | 452 | Ok(()) |
| 403 | } | 453 | } |
| 404 | 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain), | 454 | 1 => { |
| 405 | 2 => save_patches_to_dir(most_recent_proposal_patch_chain, &git_repo), | 455 | launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update) |
| 456 | } | ||
| 457 | 2 => save_patches_to_dir( | ||
| 458 | most_recent_proposal_patch_chain_or_pr_or_pr_update, | ||
| 459 | &git_repo, | ||
| 460 | ), | ||
| 406 | 3 => continue, | 461 | 3 => continue, |
| 407 | _ => { | 462 | _ => { |
| 408 | bail!("unexpected choice") | 463 | bail!("unexpected choice") |
| @@ -414,11 +469,14 @@ pub async fn launch() -> Result<()> { | |||
| 414 | git_repo.get_commits_ahead_behind(&master_tip, &local_branch_tip)?; | 469 | git_repo.get_commits_ahead_behind(&master_tip, &local_branch_tip)?; |
| 415 | 470 | ||
| 416 | // new appendments to proposal | 471 | // new appendments to proposal |
| 417 | if let Some(index) = most_recent_proposal_patch_chain.iter().position(|patch| { | 472 | if let Some(index) = most_recent_proposal_patch_chain_or_pr_or_pr_update |
| 418 | get_commit_id_from_patch(patch) | 473 | .iter() |
| 419 | .unwrap_or_default() | 474 | .position(|patch| { |
| 420 | .eq(&local_branch_tip.to_string()) | 475 | get_commit_id_from_patch(patch) |
| 421 | }) { | 476 | .unwrap_or_default() |
| 477 | .eq(&local_branch_tip.to_string()) | ||
| 478 | }) | ||
| 479 | { | ||
| 422 | return match Interactor::default().choice( | 480 | return match Interactor::default().choice( |
| 423 | PromptChoiceParms::default() | 481 | PromptChoiceParms::default() |
| 424 | .with_default(0) | 482 | .with_default(0) |
| @@ -437,7 +495,7 @@ pub async fn launch() -> Result<()> { | |||
| 437 | let _ = git_repo | 495 | let _ = git_repo |
| 438 | .apply_patch_chain( | 496 | .apply_patch_chain( |
| 439 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, | 497 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, |
| 440 | most_recent_proposal_patch_chain, | 498 | most_recent_proposal_patch_chain_or_pr_or_pr_update, |
| 441 | ) | 499 | ) |
| 442 | .context("failed to apply patch chain")?; | 500 | .context("failed to apply patch chain")?; |
| 443 | println!( | 501 | println!( |
| @@ -448,8 +506,13 @@ pub async fn launch() -> Result<()> { | |||
| 448 | ); | 506 | ); |
| 449 | Ok(()) | 507 | Ok(()) |
| 450 | } | 508 | } |
| 451 | 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain), | 509 | 1 => { |
| 452 | 2 => save_patches_to_dir(most_recent_proposal_patch_chain, &git_repo), | 510 | launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update) |
| 511 | } | ||
| 512 | 2 => save_patches_to_dir( | ||
| 513 | most_recent_proposal_patch_chain_or_pr_or_pr_update, | ||
| 514 | &git_repo, | ||
| 515 | ), | ||
| 453 | 3 => continue, | 516 | 3 => continue, |
| 454 | _ => { | 517 | _ => { |
| 455 | bail!("unexpected choice") | 518 | bail!("unexpected choice") |
| @@ -467,7 +530,7 @@ pub async fn launch() -> Result<()> { | |||
| 467 | }) { | 530 | }) { |
| 468 | println!( | 531 | println!( |
| 469 | "updated proposal available ({} ahead {} behind '{main_branch_name}'). existing version is {} ahead {} behind '{main_branch_name}'", | 532 | "updated proposal available ({} ahead {} behind '{main_branch_name}'). existing version is {} ahead {} behind '{main_branch_name}'", |
| 470 | most_recent_proposal_patch_chain.len(), | 533 | most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), |
| 471 | proposal_behind_main.len(), | 534 | proposal_behind_main.len(), |
| 472 | local_ahead_of_main.len(), | 535 | local_ahead_of_main.len(), |
| 473 | local_beind_main.len(), | 536 | local_beind_main.len(), |
| @@ -492,11 +555,11 @@ pub async fn launch() -> Result<()> { | |||
| 492 | git_repo.checkout( | 555 | git_repo.checkout( |
| 493 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, | 556 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, |
| 494 | )?; | 557 | )?; |
| 495 | let chain_length = most_recent_proposal_patch_chain.len(); | 558 | let chain_length = most_recent_proposal_patch_chain_or_pr_or_pr_update.len(); |
| 496 | let _ = git_repo | 559 | let _ = git_repo |
| 497 | .apply_patch_chain( | 560 | .apply_patch_chain( |
| 498 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, | 561 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, |
| 499 | most_recent_proposal_patch_chain, | 562 | most_recent_proposal_patch_chain_or_pr_or_pr_update, |
| 500 | ) | 563 | ) |
| 501 | .context("failed to apply patch chain")?; | 564 | .context("failed to apply patch chain")?; |
| 502 | println!( | 565 | println!( |
| @@ -520,8 +583,13 @@ pub async fn launch() -> Result<()> { | |||
| 520 | ); | 583 | ); |
| 521 | Ok(()) | 584 | Ok(()) |
| 522 | } | 585 | } |
| 523 | 2 => launch_git_am_with_patches(most_recent_proposal_patch_chain), | 586 | 2 => { |
| 524 | 3 => save_patches_to_dir(most_recent_proposal_patch_chain, &git_repo), | 587 | launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update) |
| 588 | } | ||
| 589 | 3 => save_patches_to_dir( | ||
| 590 | most_recent_proposal_patch_chain_or_pr_or_pr_update, | ||
| 591 | &git_repo, | ||
| 592 | ), | ||
| 525 | 4 => continue, | 593 | 4 => continue, |
| 526 | _ => { | 594 | _ => { |
| 527 | bail!("unexpected choice") | 595 | bail!("unexpected choice") |
| @@ -581,7 +649,7 @@ pub async fn launch() -> Result<()> { | |||
| 581 | if git_repo.does_commit_exist(&proposal_tip.to_string())? { | 649 | if git_repo.does_commit_exist(&proposal_tip.to_string())? { |
| 582 | println!( | 650 | println!( |
| 583 | "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}')", | 651 | "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}')", |
| 584 | most_recent_proposal_patch_chain.len(), | 652 | most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), |
| 585 | proposal_behind_main.len(), | 653 | proposal_behind_main.len(), |
| 586 | local_ahead_of_main.len(), | 654 | local_ahead_of_main.len(), |
| 587 | local_beind_main.len(), | 655 | local_beind_main.len(), |
| @@ -594,7 +662,7 @@ pub async fn launch() -> Result<()> { | |||
| 594 | "your local proposal branch ({} ahead {} behind '{main_branch_name}') has conflicting changes with the latest published proposal ({} ahead {} behind '{main_branch_name}')", | 662 | "your local proposal branch ({} ahead {} behind '{main_branch_name}') has conflicting changes with the latest published proposal ({} ahead {} behind '{main_branch_name}')", |
| 595 | local_ahead_of_main.len(), | 663 | local_ahead_of_main.len(), |
| 596 | local_beind_main.len(), | 664 | local_beind_main.len(), |
| 597 | most_recent_proposal_patch_chain.len(), | 665 | most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), |
| 598 | proposal_behind_main.len(), | 666 | proposal_behind_main.len(), |
| 599 | ); | 667 | ); |
| 600 | 668 | ||
| @@ -639,11 +707,11 @@ pub async fn launch() -> Result<()> { | |||
| 639 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, | 707 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, |
| 640 | &proposal_base_commit.to_string(), | 708 | &proposal_base_commit.to_string(), |
| 641 | )?; | 709 | )?; |
| 642 | let chain_length = most_recent_proposal_patch_chain.len(); | 710 | let chain_length = most_recent_proposal_patch_chain_or_pr_or_pr_update.len(); |
| 643 | let _ = git_repo | 711 | let _ = git_repo |
| 644 | .apply_patch_chain( | 712 | .apply_patch_chain( |
| 645 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, | 713 | &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?, |
| 646 | most_recent_proposal_patch_chain, | 714 | most_recent_proposal_patch_chain_or_pr_or_pr_update, |
| 647 | ) | 715 | ) |
| 648 | .context("failed to apply patch chain")?; | 716 | .context("failed to apply patch chain")?; |
| 649 | 717 | ||
| @@ -658,8 +726,11 @@ pub async fn launch() -> Result<()> { | |||
| 658 | ); | 726 | ); |
| 659 | Ok(()) | 727 | Ok(()) |
| 660 | } | 728 | } |
| 661 | 2 => launch_git_am_with_patches(most_recent_proposal_patch_chain), | 729 | 2 => launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update), |
| 662 | 3 => save_patches_to_dir(most_recent_proposal_patch_chain, &git_repo), | 730 | 3 => save_patches_to_dir( |
| 731 | most_recent_proposal_patch_chain_or_pr_or_pr_update, | ||
| 732 | &git_repo, | ||
| 733 | ), | ||
| 663 | 4 => continue, | 734 | 4 => continue, |
| 664 | _ => { | 735 | _ => { |
| 665 | bail!("unexpected choice") | 736 | bail!("unexpected choice") |