upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/bin/ngit/sub_commands/send.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-03-05 13:14:34 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-03-05 13:14:34 +0000
commitb143abb25d6ece32412629baa3e75e94d139979f (patch)
tree4ba6a68bd811e081a529e674b93ece02c7090732 /src/bin/ngit/sub_commands/send.rs
parentf3fcf863aae000964753f574b00e9fb9f5fcd452 (diff)
refactor(subject): standardise on subject over title in CLI and output
- JSON output fields renamed from title to subject in pr list/view and issue list/view - Printed view output changed from Title: to Subject: - ngit issue create --subject (alias --title) - ngit send --subject (alias --title) - Error messages and interactive prompts updated to match
Diffstat (limited to 'src/bin/ngit/sub_commands/send.rs')
-rw-r--r--src/bin/ngit/sub_commands/send.rs52
1 files changed, 26 insertions, 26 deletions
diff --git a/src/bin/ngit/sub_commands/send.rs b/src/bin/ngit/sub_commands/send.rs
index 86af2d3..e7671a2 100644
--- a/src/bin/ngit/sub_commands/send.rs
+++ b/src/bin/ngit/sub_commands/send.rs
@@ -38,9 +38,9 @@ pub struct SubCommandArgs {
38 /// don't prompt for a cover letter 38 /// don't prompt for a cover letter
39 #[arg(long, action)] 39 #[arg(long, action)]
40 pub(crate) no_cover_letter: bool, 40 pub(crate) no_cover_letter: bool,
41 /// optional cover letter title 41 /// optional cover letter subject/title
42 #[clap(long)] 42 #[clap(long, alias = "title")]
43 pub(crate) title: Option<String>, 43 pub(crate) subject: Option<String>,
44 #[clap(long)] 44 #[clap(long)]
45 /// optional cover letter description 45 /// optional cover letter description
46 pub(crate) description: Option<String>, 46 pub(crate) description: Option<String>,
@@ -73,23 +73,23 @@ fn validate_send_args(cli: &Cli, args: &SubCommandArgs) -> Result<()> {
73 return Ok(()); 73 return Ok(());
74 } 74 }
75 75
76 // Description requires title 76 // Description requires subject
77 if args.description.is_some() && args.title.is_none() { 77 if args.description.is_some() && args.subject.is_none() {
78 let message = "ngit send requires --title when --description is provided"; 78 let message = "ngit send requires --subject when --description is provided";
79 let details = vec![("--title <T>", "cover letter title")]; 79 let details = vec![("--subject <T>", "cover letter subject")];
80 let suggestions = vec![ 80 let suggestions = vec![
81 "ngit send HEAD~2 --title \"My Feature\" --description \"Details\"", 81 "ngit send HEAD~2 --subject \"My Feature\" --description \"Details\"",
82 "ngit send --interactive", 82 "ngit send --interactive",
83 ]; 83 ];
84 return Err(cli_error(message, &details, &suggestions)); 84 return Err(cli_error(message, &details, &suggestions));
85 } 85 }
86 86
87 // Title requires description 87 // Subject requires description
88 if args.title.is_some() && args.description.is_none() { 88 if args.subject.is_some() && args.description.is_none() {
89 let message = "ngit send requires --description when --title is provided"; 89 let message = "ngit send requires --description when --subject is provided";
90 let details = vec![("--description <D>", "cover letter description")]; 90 let details = vec![("--description <D>", "cover letter description")];
91 let suggestions = vec![ 91 let suggestions = vec![
92 "ngit send HEAD~2 --title \"My Feature\" --description \"Details\"", 92 "ngit send HEAD~2 --subject \"My Feature\" --description \"Details\"",
93 "ngit send --interactive", 93 "ngit send --interactive",
94 ]; 94 ];
95 return Err(cli_error(message, &details, &suggestions)); 95 return Err(cli_error(message, &details, &suggestions));
@@ -105,8 +105,8 @@ fn validate_send_args(cli: &Cli, args: &SubCommandArgs) -> Result<()> {
105 return Ok(()); 105 return Ok(());
106 } 106 }
107 107
108 // Both title and description provided - all good 108 // Both subject and description provided - all good
109 if args.title.is_some() && args.description.is_some() { 109 if args.subject.is_some() && args.description.is_some() {
110 return Ok(()); 110 return Ok(());
111 } 111 }
112 112
@@ -121,11 +121,11 @@ fn validate_send_args(cli: &Cli, args: &SubCommandArgs) -> Result<()> {
121 if args.since_or_range.is_empty() { 121 if args.since_or_range.is_empty() {
122 details.push(("<SINCE_OR_RANGE>", "commits to send (eg. HEAD~2)")); 122 details.push(("<SINCE_OR_RANGE>", "commits to send (eg. HEAD~2)"));
123 } 123 }
124 details.push(("--title <T> --description <D>", "cover letter details")); 124 details.push(("--subject <T> --description <D>", "cover letter details"));
125 details.push(("-d, --defaults", "use sensible defaults")); 125 details.push(("-d, --defaults", "use sensible defaults"));
126 details.push(("--interactive", "prompt for values")); 126 details.push(("--interactive", "prompt for values"));
127 let suggestions = vec![ 127 let suggestions = vec![
128 "ngit send HEAD~2 --title \"My Feature\" --description \"Details\"", 128 "ngit send HEAD~2 --subject \"My Feature\" --description \"Details\"",
129 "ngit send --defaults", 129 "ngit send --defaults",
130 "ngit send --interactive", 130 "ngit send --interactive",
131 ]; 131 ];
@@ -252,13 +252,13 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re
252 let cover_letter_title_description = if cli_args.interactive { 252 let cover_letter_title_description = if cli_args.interactive {
253 // Interactive flow: prompt for cover letter confirm, title, description 253 // Interactive flow: prompt for cover letter confirm, title, description
254 let title = if as_pr { 254 let title = if as_pr {
255 match &args.title { 255 match &args.subject {
256 Some(t) => Some(t.clone()), 256 Some(t) => Some(t.clone()),
257 None => { 257 None => {
258 if root_proposal.is_none() { 258 if root_proposal.is_none() {
259 Some( 259 Some(
260 Interactor::default() 260 Interactor::default()
261 .input(PromptInputParms::default().with_prompt("title"))? 261 .input(PromptInputParms::default().with_prompt("subject"))?
262 .clone(), 262 .clone(),
263 ) 263 )
264 } else { 264 } else {
@@ -269,7 +269,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re
269 } else if args.no_cover_letter { 269 } else if args.no_cover_letter {
270 None 270 None
271 } else { 271 } else {
272 match &args.title { 272 match &args.subject {
273 Some(t) => Some(t.clone()), 273 Some(t) => Some(t.clone()),
274 None => { 274 None => {
275 if Interactor::default().confirm( 275 if Interactor::default().confirm(
@@ -279,7 +279,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re
279 )? { 279 )? {
280 Some( 280 Some(
281 Interactor::default() 281 Interactor::default()
282 .input(PromptInputParms::default().with_prompt("title"))? 282 .input(PromptInputParms::default().with_prompt("subject"))?
283 .clone(), 283 .clone(),
284 ) 284 )
285 } else { 285 } else {
@@ -305,12 +305,12 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re
305 } 305 }
306 } else if as_pr { 306 } else if as_pr {
307 // PR always needs cover letter 307 // PR always needs cover letter
308 let title = match &args.title { 308 let title = match &args.subject {
309 Some(t) => t.clone(), 309 Some(t) => t.clone(),
310 None if cli_args.defaults => { 310 None if cli_args.defaults => {
311 git_repo.get_commit_message_summary(commits.first().context("no commits")?)? 311 git_repo.get_commit_message_summary(commits.first().context("no commits")?)?
312 } 312 }
313 None => bail!("PR requires --title and --description (or use --defaults)"), 313 None => bail!("PR requires --subject and --description (or use --defaults)"),
314 }; 314 };
315 let description = match &args.description { 315 let description = match &args.description {
316 Some(d) => d.clone(), 316 Some(d) => d.clone(),
@@ -324,15 +324,15 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs, no_fetch: bool) -> Re
324 .trim() 324 .trim()
325 .to_string() 325 .to_string()
326 } 326 }
327 None => bail!("PR requires --title and --description (or use --defaults)"), 327 None => bail!("PR requires --subject and --description (or use --defaults)"),
328 }; 328 };
329 Some((title, description)) 329 Some((title, description))
330 } else { 330 } else {
331 // Patch mode 331 // Patch mode
332 match (&args.title, &args.description) { 332 match (&args.subject, &args.description) {
333 (Some(t), Some(d)) => Some((t.clone(), d.clone())), 333 (Some(t), Some(d)) => Some((t.clone(), d.clone())),
334 (Some(_), None) => bail!("--title requires --description"), 334 (Some(_), None) => bail!("--subject requires --description"),
335 (None, Some(_)) => bail!("--description requires --title"), 335 (None, Some(_)) => bail!("--description requires --subject"),
336 (None, None) => None, // no cover letter 336 (None, None) => None, // no cover letter
337 } 337 }
338 }; 338 };