jirust_cli/args/
commands.rs

1use crate::jira_doc_std_field;
2use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum};
3use regex::Regex;
4use serde::{Deserialize, Serialize};
5use std::error::Error;
6
7/// Command line arguments base
8/// subcommands: Config, Version
9#[derive(Parser, Debug)]
10#[command(author, version, about, long_about = None)]
11pub struct JirustCliArgs {
12    /// Subcommands
13    #[clap(subcommand)]
14    pub subcmd: Commands,
15}
16
17/// Available CLI commands
18/// Config, Issue, Project, Transition, Version
19#[derive(Subcommand, Clone, Debug, Serialize, Deserialize)]
20pub enum Commands {
21    /// Configuration management
22    Config(ConfigArgs),
23    /// Issue management
24    Issue(IssueArgs),
25    /// Issue links management
26    Link(LinkIssueArgs),
27    /// Project management
28    Project(ProjectArgs),
29    /// Transition management
30    Transition(TransitionArgs),
31    /// Version management
32    Version(VersionArgs),
33}
34
35/// Available pagination command line arguments
36///
37/// * page_size: `Option<i32>`
38/// * page_offset: `Option<i64>`
39#[derive(Args, Clone, Debug, Serialize, Deserialize)]
40pub struct PaginationArgs {
41    /// page size for lists
42    #[clap(
43        long,
44        short = 'l',
45        value_name = "page_size",
46        help = "page size for lists"
47    )]
48    pub page_size: Option<i32>,
49    /// page offset for list
50    #[clap(
51        long,
52        short = 's',
53        value_name = "page_offset",
54        help = "page offset for list"
55    )]
56    pub page_offset: Option<i64>,
57}
58
59/// Available output values
60/// Table, Json
61///
62/// * Table: Print output in table format
63/// * Json: Print output in json format
64#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
65#[value(rename_all = "kebab-case")]
66pub enum OutputValues {
67    /// Print output in table format
68    #[value(name = "table", help = "Print output in table format")]
69    Table,
70    /// Print output in json format
71    #[value(name = "json", help = "Print output in json format")]
72    Json,
73}
74
75/// Available output types
76/// Table, Json
77///
78/// * Basic: Print basic output
79/// * Single: Print single row output
80/// * Full: Print full output
81#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
82#[value(rename_all = "kebab-case")]
83pub enum OutputTypes {
84    /// Print basic output
85    #[value(name = "basic", help = "Print basic output")]
86    Basic,
87    /// Print single row output
88    #[value(name = "single", help = "Print single row output")]
89    Single,
90    /// Print full output
91    #[value(name = "full", help = "Print full output")]
92    Full,
93}
94
95/// Available output values
96///
97/// * output: `Option<OutputValues>` - Output format
98#[derive(Args, Clone, Debug, Serialize, Deserialize)]
99pub struct OutputArgs {
100    /// Output format
101    #[clap(long, short = 'o', value_name = "table|json", help = "Output format")]
102    pub output_format: Option<OutputValues>,
103    /// Output type
104    #[clap(
105        long,
106        short = 'z',
107        value_name = "basic|single|full",
108        help = "Output type"
109    )]
110    pub output_type: Option<OutputTypes>,
111}
112
113/// Available configuration command line arguments
114/// cfg_act: ConfigActionValues
115///    Auth, Jira, Setup, Show
116#[derive(Args, Clone, Debug, Serialize, Deserialize)]
117pub struct ConfigArgs {
118    /// Configuration action
119    #[arg(
120        value_name = "auth|jira|setup|show",
121        help_heading = "Configuration management"
122    )]
123    pub cfg_act: ConfigActionValues,
124}
125
126/// Available configuration action values
127/// Auth, Jira, Setup, Show
128///
129/// * Auth: Set Jira API authentication (username, apikey)
130/// * Jira: Set Jira API base URL
131/// * Setup: Setup Jira API configuration (authentication data, jira base URL, etc.)
132/// * Show: Show current configuration
133#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
134#[value(rename_all = "kebab-case")]
135pub enum ConfigActionValues {
136    /// Set Jira API authentication (username, apikey)
137    #[value(name = "auth", help = "Set Jira API authentication (username, apikey)")]
138    Auth,
139    /// Set Jira API base URL
140    #[value(name = "jira", help = "Set Jira API base URL")]
141    Jira,
142    /// Setup Jira API configuration (authentication data, jira base URL, etc.)
143    #[value(
144        name = "setup",
145        help = "Setup Jira API configuration (authentication data, jira base URL, etc.)"
146    )]
147    Setup,
148    /// Show current configuration
149    #[value(name = "show", help = "Show current configuration")]
150    Show,
151}
152
153/// Available version command line arguments
154///
155/// * version_act: VersionActionValues - Version action
156/// * project_key: String - Jira Project key
157/// * project_id: `Option<i64>` - Jira Project ID
158/// * version_id: `Option<String>` - Jira Project version ID
159/// * version_name: `Option<String>` - Jira Project version name
160/// * version_description: `Option<String>` - Jira Project version description
161/// * version_start_date: `Option<String>` - Jira Project version start date
162/// * version_release_date: `Option<String>` - Jira Project version release date
163/// * version_archived: `Option<bool>` - Jira Project version archived
164/// * version_released: `Option<bool>` - Jira Project version released
165/// * changelog_file: `Option<String>` - Jira Project version changelog file
166/// * transition_issues: `Option<bool>` - Jira Project version automatically transition issues in changelog
167/// * transition_assignee: `Option<String>` - Jira Project version transition assignee
168/// * pagination: PaginationArgs - Jira Project version pagination
169/// * output: OutputArgs - Jira Project version actions result output format
170///
171#[derive(Args, Clone, Debug, Serialize, Deserialize)]
172pub struct VersionArgs {
173    /// Version action
174    #[arg(
175        value_name = "archive|create|delete|list|release|update",
176        help_heading = "Jira Project version management"
177    )]
178    pub version_act: VersionActionValues,
179    /// Jira Project key
180    #[clap(
181        long,
182        short = 'k',
183        value_name = "project_key",
184        required = true,
185        help = "Jira Project key"
186    )]
187    pub project_key: String,
188    /// Jira Project ID
189    #[clap(long, short = 'i', value_name = "project_id", help = "Jira Project ID")]
190    pub project_id: Option<i64>,
191    /// Jira Project version ID
192    #[clap(
193        long,
194        short = 'v',
195        value_name = "version_id",
196        help = "Jira Project version ID"
197    )]
198    pub version_id: Option<String>,
199    /// Jira Project version name
200    #[clap(
201        long,
202        short = 'n',
203        value_name = "version_name",
204        help = "Jira Project version name"
205    )]
206    pub version_name: Option<String>,
207    /// Jira Project version description
208    #[clap(
209        long,
210        short = 'd',
211        value_name = "version_description",
212        help = "Jira Project version description"
213    )]
214    pub version_description: Option<String>,
215    /// Jira Project version start date
216    #[clap(
217        long,
218        value_name = "version_start_date",
219        help = "Jira Project version start date"
220    )]
221    pub version_start_date: Option<String>,
222    /// Jira Project version release date
223    #[clap(
224        long,
225        value_name = "version_release_date",
226        help = "Jira Project version release date"
227    )]
228    pub version_release_date: Option<String>,
229    /// Jira Project version archived
230    #[clap(
231        long,
232        short = 'a',
233        value_name = "version_archived",
234        help = "Jira Project version archived"
235    )]
236    pub version_archived: Option<bool>,
237    /// Jira Project version released
238    #[clap(
239        long,
240        short = 'm',
241        action = ArgAction::SetTrue,
242        value_name = "version_released",
243        help = "Jira Project version released"
244    )]
245    pub version_released: Option<bool>,
246    /// Jira Project version changelog file
247    #[clap(
248        long,
249        short = 'c',
250        value_name = "changelog_file",
251        help = "changelog file path to be used for automatic description generation (if set the script detects automatically the first tagged block in the changelog and use it as description)"
252    )]
253    pub changelog_file: Option<String>,
254    /// Jira Project version automatically transition issues in changelog
255    #[clap(
256        long,
257        short = 'r',
258        action = ArgAction::SetTrue,
259        value_name = "resolve_issues",
260        help = "if changelog is set and this flag is set, the script will transition all issues in the changelog of the current version release to the \"resolved\" status setting the version as \"fixVersion\""
261    )]
262    pub transition_issues: Option<bool>,
263    /// Jira Project version transition assignee
264    #[clap(
265        long,
266        short = 'u',
267        value_name = "transition_assignee",
268        help = "if changelog is set and the resolve_issues flag is set, the script will assigned all the resolved issue to the user specified in this field (if not set the assignee will not be changed)"
269    )]
270    pub transition_assignee: Option<String>,
271    /// Jira Project version pagination
272    #[clap(flatten)]
273    pub pagination: PaginationArgs,
274    /// Jira Project version actions result output format
275    #[clap(flatten)]
276    pub output: OutputArgs,
277}
278
279/// Available version action values
280/// Archive, Create, Delete, List, Release, Update
281///
282/// * Archive: Archive a Jira Project version
283/// * Create: Create a Jira Project version
284/// * Delete: Delete a Jira Project version
285/// * List: List Jira Project versions
286/// * RelatedWorkItems: Get Project version related workitems
287/// * Release: Release a Jira Project version
288/// * Update: Update a Jira Project version
289#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
290#[value(rename_all = "kebab-case")]
291pub enum VersionActionValues {
292    /// Archive a Jira Project version
293    #[value(name = "archive", help = "Archive a Jira Project version")]
294    Archive,
295    /// Create a Jira Project version
296    #[value(name = "create", help = "Create a Jira Project version")]
297    Create,
298    /// Delete a Jira Project version
299    #[value(name = "delete", help = "Delete a Jira Project version")]
300    Delete,
301    /// List Jira Project versions
302    #[value(name = "list", help = "List Jira Project versions")]
303    List,
304    /// Get Project version related workitems
305    #[value(
306        name = "related-work-items",
307        help = "Get Project version related workitems"
308    )]
309    RelatedWorkItems,
310    /// Release a Jira Project version
311    #[value(name = "release", help = "Release a Jira Project version")]
312    Release,
313    /// Update a Jira Project version
314    #[value(name = "update", help = "Update a Jira Project version")]
315    Update,
316}
317
318/// Available project command line arguments
319///
320/// * project_act: ProjectActionValues - Project action
321/// * project_key: `Option<String>` - Jira Project key
322/// * project_issue_type: `Option<String>` - Jira Project issue type ID
323/// * project_name: `Option<String>` - Jira Project name
324/// * project_description: `Option<String>` - Jira Project description
325/// * project_field_configuration_id: `Option<i64>` - Jira Project field configuration ID
326/// * project_issue_security_scheme_id: `Option<i64>` - Jira Project issue security scheme ID
327/// * project_permission_scheme_id: `Option<i64>` - Jira Project permission scheme ID
328/// * project_issue_type_scheme_id: `Option<i64>` - Jira Project issue type scheme ID
329/// * project_issue_type_screen_scheme_id: `Option<i64>` - Jira Project issue type screen scheme ID
330/// * project_notification_scheme_id: `Option<i64>` - Jira Project notification scheme ID
331/// * project_workflow_scheme_id: `Option<i64>` - Jira Project workflow scheme ID
332/// * project_lead_account_id: `Option<String>` - Jira Project lead account ID
333/// * project_assignee_type: `Option<String>` - Jira Project assignee type
334/// * pagination: PaginationArgs - Jira Project pagination
335/// * output: OutputArgs - Jira Project actions result output format
336#[derive(Args, Clone, Debug, Serialize, Deserialize)]
337pub struct ProjectArgs {
338    /// Project action
339    #[arg(
340        value_name = "create|get-issue-types|get-issue-type-fields|list",
341        help_heading = "Jira Project management",
342        required = true
343    )]
344    pub project_act: ProjectActionValues,
345    /// Jira Project key
346    #[clap(
347        long,
348        short = 'k',
349        value_name = "project_key",
350        help = "Jira Project key"
351    )]
352    pub project_key: Option<String>,
353    /// Jira Project issue type ID
354    #[clap(
355        long,
356        short = 'i',
357        value_name = "project_issue_type",
358        help = "Jira Project issue type ID"
359    )]
360    pub project_issue_type: Option<String>,
361    /// Jira Project name
362    #[clap(long, value_name = "project_name", help = "Jira Project name")]
363    pub project_name: Option<String>,
364    /// Jira Project description
365    #[clap(
366        long,
367        value_name = "project_description",
368        help = "Jira Project description"
369    )]
370    pub project_description: Option<String>,
371    /// Jira Project field configuration ID
372    #[clap(
373        long,
374        value_name = "project_field_configuration_id",
375        help = "Jira Project field configuration ID"
376    )]
377    pub project_field_configuration_id: Option<i64>,
378    /// Jira Project issue security scheme ID
379    #[clap(
380        long,
381        value_name = "project_issue_security_scheme_id",
382        help = "Jira Project issue security scheme ID"
383    )]
384    pub project_issue_security_scheme_id: Option<i64>,
385    /// Jira Project issue type scheme ID
386    #[clap(
387        long,
388        value_name = "project_issue_type_scheme_id",
389        help = "Jira Project issue type scheme ID"
390    )]
391    pub project_issue_type_scheme_id: Option<i64>,
392    /// Jira Project issue type screen scheme ID
393    #[clap(
394        long,
395        value_name = "project_issue_type_screen_scheme_id",
396        help = "Jira Project issue type screen scheme ID"
397    )]
398    pub project_issue_type_screen_scheme_id: Option<i64>,
399    /// Jira Project notification scheme ID
400    #[clap(
401        long,
402        value_name = "project_notification_scheme_id",
403        help = "Jira Project notification scheme ID"
404    )]
405    pub project_notification_scheme_id: Option<i64>,
406    /// Jira Project permission scheme ID
407    #[clap(
408        long,
409        value_name = "project_permission_scheme_id",
410        help = "Jira Project permission scheme ID"
411    )]
412    pub project_permission_scheme_id: Option<i64>,
413    /// Jira project workflow scheme ID
414    #[clap(
415        long,
416        value_name = "project_workflow_scheme_id",
417        help = "Jira Project workflow scheme ID"
418    )]
419    pub project_workflow_scheme_id: Option<i64>,
420    /// Jira Project lead account ID
421    #[clap(
422        long,
423        value_name = "project_lead_account_id",
424        help = "Jira Project lead account ID"
425    )]
426    pub project_lead_account_id: Option<String>,
427    /// Jira Project Assignee Type
428    #[clap(
429        long,
430        value_name = "project_assignee_type",
431        help = "Jira Project Assignee Type"
432    )]
433    pub project_assignee_type: Option<String>,
434    /// Jira Project pagination
435    #[clap(flatten)]
436    pub pagination: PaginationArgs,
437    /// Jira Project actions result output format
438    #[clap(flatten)]
439    pub output: OutputArgs,
440}
441
442/// Available project action values
443///
444/// * Create: Create new Jira Project
445/// * GetIssueTypes: Get Jira Project issue types by Jira project key
446/// * GetIssueTypeFields: Get Jira Project issue type fields by Jira project key and issue type ID
447/// * List: List Jira Projects
448#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
449#[value(rename_all = "kebab-case")]
450pub enum ProjectActionValues {
451    /// Create new Jira Project
452    #[value(name = "create", help = "Create new Jira Project")]
453    Create,
454    /// Get Jira Project issue types by Jira project key
455    #[value(
456        name = "get-issue-types",
457        help = "Get Jira Project issue types by Jira project key"
458    )]
459    GetIssueTypes,
460    /// Get Jira Project issue type fields by Jira project key and issue type ID
461    #[value(
462        name = "get-issue-type-fields",
463        help = "Get Jira Project issue type fields by Jira project key and issue type ID"
464    )]
465    GetIssueTypeFields,
466    /// List Jira Projects
467    #[value(name = "list", help = "List Jira Projects")]
468    List,
469}
470
471/// Available issue command line arguments
472///
473/// * issue_act: IssueActionValues - Issue action
474/// * project_key: String - Jira Project key
475/// * issue_key: `Option<String>` - Jira Project issue key
476/// * issue_fields: `Option<Vec<(String, String)>>` - Jira Project issue fields
477/// * transition_to: `Option<String>` - Jira Project issue transition to
478/// * assignee: `Option<String>` - Jira Project issue assignee
479/// * query: `Option<String>` - Jira Project issue JQL query to search for issues
480/// * pagination: PaginationArgs - Jira Project issue pagination
481/// * output: OutputArgs - Jira Project issue actions result output format
482#[derive(Args, Clone, Debug, Serialize, Deserialize)]
483pub struct IssueArgs {
484    /// Issue action
485    #[arg(
486        value_name = "assign|create|delete|get|search|transition|update",
487        help_heading = "Jira Project issue management",
488        required = true
489    )]
490    pub issue_act: IssueActionValues,
491    /// Jira Project key
492    #[clap(
493        long,
494        short = 'k',
495        value_name = "project_key",
496        help = "Jira Project key"
497    )]
498    pub project_key: Option<String>,
499    /// Jira Project issue key
500    #[clap(
501        long,
502        short = 'i',
503        value_name = "issue_key",
504        help = "Jira Project issue key"
505    )]
506    pub issue_key: Option<String>,
507    /// Jira Project issue fields
508    #[clap(long,
509        short = 'f',
510        value_name = "issue_fields",
511        value_parser = parse_key_val::<String, String>,
512        help = "Jira Project issue fields (field_name=value)")]
513    pub issue_fields: Option<Vec<(String, String)>>,
514    /// Jira Project issue transition
515    #[clap(
516        long,
517        short = 't',
518        value_name = "transition_to",
519        help = "Jira Project issue transition to"
520    )]
521    pub transition_to: Option<String>,
522    /// Jira Project issue assignee
523    #[clap(
524        long,
525        short = 'a',
526        value_name = "assignee",
527        help = "Jira Project issue assignee"
528    )]
529    pub assignee: Option<String>,
530    /// Jira Project issue query
531    #[clap(
532        long,
533        short = 'q',
534        value_name = "query",
535        help = "Jira Project issue query"
536    )]
537    pub query: Option<String>,
538    /// Jira Project issue attachments file path
539    #[clap(
540        long,
541        short = 'p',
542        value_name = "attachment_file_path",
543        help = "Jira Project issue attachment file path"
544    )]
545    pub attachment_file_path: Option<String>,
546    /// Jira Project issue pagination
547    #[clap(flatten)]
548    pub pagination: PaginationArgs,
549    /// Jira Project issue actions result output format
550    #[clap(flatten)]
551    pub output: OutputArgs,
552}
553
554/// Available issue action values
555///
556/// * Assign: Assign a Jira Project issue
557/// * Attach: Attach a file to a Jira Project issue
558/// * Create: Create a Jira Project issue
559/// * Delete: Delete a Jira Project issue
560/// * Get: Get a specific Jira Project issue
561/// * Search: Search for Jira Project issues using JQL
562/// * Transition: Transition a Jira Project issue
563/// * Update: Update a Jira Project issue
564#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
565#[value(rename_all = "kebab-case")]
566pub enum IssueActionValues {
567    /// Assign a Jira Project issue
568    #[value(name = "assign", help = "Assign a Jira Project issue")]
569    Assign,
570    /// Attach a file to a Jira Project issue
571    #[value(name = "attach", help = "Attach a file to a Jira Project issue")]
572    Attach,
573    /// Create a Jira Project issue
574    #[value(name = "create", help = "Create a Jira Project issue")]
575    Create,
576    /// Delete a Jira Project issue
577    #[value(name = "delete", help = "Delete a Jira Project issue")]
578    Delete,
579    /// Get a specific Jira Project issue
580    #[value(name = "get", help = "Get a specific Jira Project issue")]
581    Get,
582    /// Search for Jira Project issues using JQL query
583    #[value(name = "search", help = "Search for Jira Project issues")]
584    Search,
585    /// Transition a Jira Project issue
586    #[value(name = "transition", help = "Transition a Jira Project issue")]
587    Transition,
588    /// Update a Jira Project issue
589    #[value(name = "update", help = "Update a Jira Project issue")]
590    Update,
591}
592
593/// Available issues' links command line arguments
594///
595/// * link_act: LinkIssueActionValues - Jira link issue command available actions
596/// * project_key: `Option<String>` - Jira Project key
597/// * origin_issue_key: String - Jira origin issue link key
598/// * destination_issue_key: `Option<String>` - Jira destination issue link key
599/// * link_type: String - Jira issue link type
600/// * changelog_file: `Option<String>` - Jira Project version changelog file
601#[derive(Args, Clone, Debug, Serialize, Deserialize)]
602pub struct LinkIssueArgs {
603    /// Jira link issue command available actions
604    #[arg(
605        value_name = "create",
606        help_heading = "Jira issues links management",
607        required = true
608    )]
609    pub link_act: LinkIssueActionValues,
610    /// Jira Project key
611    #[clap(
612        long,
613        short = 'p',
614        value_name = "project_key",
615        help = "Jira Project key"
616    )]
617    pub project_key: Option<String>,
618    /// Jira origin issue link key
619    #[clap(
620        long,
621        short = 'i',
622        value_name = "issue_key",
623        help = "Jira issue link origin key",
624        required = true
625    )]
626    pub origin_issue_key: String,
627    /// Jira destination issue link key
628    #[clap(
629        long,
630        short = 'd',
631        value_name = "issue_key",
632        help = "Jira issue link destination key"
633    )]
634    pub destination_issue_key: Option<String>,
635    /// Jira issue link type
636    #[clap(
637        long,
638        short = 't',
639        value_name = "link_type",
640        help = "Jira issue link type",
641        required = true
642    )]
643    pub link_type: String,
644    /// Jira Project version changelog file
645    #[clap(
646        long,
647        short = 'c',
648        value_name = "changelog_file",
649        help = "changelog file path to be used for automatic issues' links generation (if set the script detects automatically the first tagged block in the changelog and use it as description)"
650    )]
651    pub changelog_file: Option<String>,
652}
653
654/// Available link issue action values
655///
656/// * Create: Create a Jira link between issues
657#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
658#[value(rename_all = "kebab-case")]
659pub enum LinkIssueActionValues {
660    /// Create a Jira link between issues
661    #[value(name = "create", help = "Create a Jira link between issues")]
662    Create,
663}
664
665/// Available transition command line arguments
666///
667/// * transition_act: TransitionActionValues - Transition action
668/// * issue_key: String - Jira issue key
669/// * output: OutputArgs - Jira issue output format
670#[derive(Args, Clone, Debug, Serialize, Deserialize)]
671pub struct TransitionArgs {
672    /// Transition action
673    #[arg(value_name = "list", help_heading = "Jira issue transition list")]
674    pub transition_act: TransitionActionValues,
675    /// Jira issue key
676    #[clap(
677        long,
678        short = 'i',
679        value_name = "issue_key",
680        help = "Jira Project issue key",
681        required = true
682    )]
683    pub issue_key: String,
684    /// Jira issue output format
685    #[clap(flatten)]
686    pub output: OutputArgs,
687}
688
689/// Available transition action values
690///
691/// * List: List Jira issue available transitions
692#[derive(ValueEnum, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
693#[value(rename_all = "kebab-case")]
694pub enum TransitionActionValues {
695    /// List Jira issue available transitions
696    #[value(name = "list", help = "List Jira issue available transitions")]
697    List,
698}
699
700/// Parse a single key-value pair
701/// Thanks to the example from the clap documentation (https://github.com/clap-rs/clap/blob/master/examples/typed-derive.rs)
702fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
703where
704    T: std::str::FromStr,
705    T::Err: Error + Send + Sync + 'static,
706    U: std::str::FromStr,
707    U::Err: Error + Send + Sync + 'static,
708{
709    let pos = s
710        .find('=')
711        .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?;
712    Ok((
713        s[..pos].parse()?,
714        manage_jira_document_field(s[pos + 1..].to_string()).parse()?,
715    ))
716}
717
718/// Manage Jira document field
719/// Relies on the manage_jira_document_field macro to wrap the field in the correct format
720fn manage_jira_document_field(value: String) -> String {
721    let re = Regex::new(r"^jira_doc_field\[(.+)\]$").unwrap();
722    let captures = re.captures(&value);
723    if let Some(captures) = &captures {
724        if let Some(first_match) = captures.get(1) {
725            jira_doc_std_field![first_match.as_str()].to_string()
726        } else {
727            value.to_string()
728        }
729    } else {
730        value.to_string()
731    }
732}
733
734#[cfg(test)]
735mod tests {
736    use super::*;
737
738    #[test]
739    fn test_parse_key_val_success() {
740        let result: Result<(String, String), _> = parse_key_val("key=value");
741        assert!(result.is_ok());
742        let (key, value) = result.unwrap();
743        assert_eq!(key, "key");
744        assert_eq!(value, "value");
745    }
746
747    #[test]
748    fn test_parse_key_val_with_jira_doc_field() {
749        let result: Result<(String, String), _> = parse_key_val("key=normal_value");
750        assert!(result.is_ok());
751        let (key, value) = result.unwrap();
752        assert_eq!(key, "key");
753        assert_eq!(value, "normal_value");
754    }
755
756    #[test]
757    fn test_parse_key_val_missing_equals() {
758        let result: Result<(String, String), _> = parse_key_val("invalid");
759        assert!(result.is_err());
760    }
761
762    #[test]
763    fn test_manage_jira_document_field_no_match() {
764        let result = manage_jira_document_field("normal_value".to_string());
765        assert_eq!(result, "normal_value");
766    }
767
768    #[test]
769    fn test_manage_jira_document_field_empty_brackets() {
770        let input = "jira_doc_field[]".to_string();
771        let result = manage_jira_document_field(input.clone());
772        // Should return original value when brackets are empty
773        assert_eq!(result, input);
774    }
775}