1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use clap::Parser;

use crate::cmds::project::ProjectMetadataGetCliArgs;

use super::common::{validate_project_repo_path, GetArgs, ListArgs};

#[derive(Parser)]
pub struct ProjectCommand {
    #[clap(subcommand)]
    subcommand: ProjectSubcommand,
}

#[derive(Parser)]
enum ProjectSubcommand {
    #[clap(about = "Gather project information metadata")]
    Info(ProjectInfo),
}

#[derive(Parser)]
struct ProjectInfo {
    /// ID of the project
    #[clap(long, group = "id_or_repo")]
    pub id: Option<i64>,
    /// Path of the project in the format `OWNER/PROJECT_NAME`
    #[clap(long, group = "id_or_repo", value_name = "OWNER/PROJECT_NAME", value_parser=validate_project_repo_path)]
    pub repo: Option<String>,
    #[clap(flatten)]
    pub get_args: GetArgs,
}

#[derive(Parser)]
pub struct ListProject {
    #[clap(flatten)]
    pub list_args: ListArgs,
}

impl From<ProjectCommand> for ProjectOptions {
    fn from(options: ProjectCommand) -> Self {
        match options.subcommand {
            ProjectSubcommand::Info(options) => options.into(),
        }
    }
}

impl From<ProjectInfo> for ProjectOptions {
    fn from(options: ProjectInfo) -> Self {
        ProjectOptions::Info(
            ProjectMetadataGetCliArgs::builder()
                .id(options.id)
                .path(options.repo)
                .get_args(options.get_args.into())
                .build()
                .unwrap(),
        )
    }
}

pub enum ProjectOptions {
    Info(ProjectMetadataGetCliArgs),
}

#[cfg(test)]
mod test {
    use crate::cli::{Args, Command};

    use super::*;

    #[test]
    fn test_project_cli_info() {
        let args = Args::parse_from(vec!["gr", "pj", "info", "--id", "1"]);
        let project_info = match args.command {
            Command::Project(ProjectCommand {
                subcommand: ProjectSubcommand::Info(options),
            }) => {
                assert_eq!(options.id, Some(1));
                options
            }
            _ => panic!("Expected ProjectCommand::Info"),
        };
        let options: ProjectOptions = project_info.into();
        match options {
            ProjectOptions::Info(options) => {
                assert_eq!(options.id, Some(1));
            }
        }
    }
}