mod attachments;
mod comments;
mod crud;
mod transitions;
use std::path::PathBuf;
use anyhow::Result;
use clap::Subcommand;
use crate::output::OutputFormat;
use raps_acc::IssuesClient;
#[derive(Debug, Subcommand)]
pub enum IssueCommands {
List {
project_id: String,
#[arg(short, long)]
status: Option<String>,
#[arg(long)]
since: Option<String>,
},
Create {
project_id: String,
#[arg(short, long)]
title: Option<String>,
#[arg(short, long)]
description: Option<String>,
#[arg(long, value_name = "FILE")]
from_csv: Option<PathBuf>,
},
Update {
project_id: String,
issue_id: String,
#[arg(short, long)]
status: Option<String>,
#[arg(short, long)]
title: Option<String>,
},
Types {
project_id: String,
},
#[command(subcommand)]
Comment(CommentCommands),
Attachments {
project_id: String,
issue_id: String,
},
Transition {
project_id: String,
issue_id: String,
#[arg(short, long)]
to: Option<String>,
},
Delete {
project_id: String,
issue_id: String,
},
}
#[derive(Debug, Subcommand)]
pub enum CommentCommands {
List {
project_id: String,
issue_id: String,
},
Add {
project_id: String,
issue_id: String,
#[arg(short, long)]
body: String,
},
Delete {
project_id: String,
issue_id: String,
comment_id: String,
},
}
impl IssueCommands {
pub async fn execute(self, client: &IssuesClient, output_format: OutputFormat) -> Result<()> {
match self {
IssueCommands::List {
project_id,
status,
since,
} => crud::list_issues(client, &project_id, status, since, output_format).await,
IssueCommands::Create {
project_id,
title,
description,
from_csv,
} => {
crud::create_issue(
client,
&project_id,
title,
description,
from_csv,
output_format,
)
.await
}
IssueCommands::Update {
project_id,
issue_id,
status,
title,
} => {
crud::update_issue(client, &project_id, &issue_id, status, title, output_format)
.await
}
IssueCommands::Types { project_id } => {
crud::list_issue_types(client, &project_id, output_format).await
}
IssueCommands::Comment(cmd) => cmd.execute(client, output_format).await,
IssueCommands::Attachments {
project_id,
issue_id,
} => attachments::list_attachments(client, &project_id, &issue_id, output_format).await,
IssueCommands::Transition {
project_id,
issue_id,
to,
} => {
transitions::transition_issue(client, &project_id, &issue_id, to, output_format)
.await
}
IssueCommands::Delete {
project_id,
issue_id,
} => crud::delete_issue(client, &project_id, &issue_id, output_format).await,
}
}
}
impl CommentCommands {
pub async fn execute(self, client: &IssuesClient, output_format: OutputFormat) -> Result<()> {
match self {
CommentCommands::List {
project_id,
issue_id,
} => comments::list_comments(client, &project_id, &issue_id, output_format).await,
CommentCommands::Add {
project_id,
issue_id,
body,
} => comments::add_comment(client, &project_id, &issue_id, &body, output_format).await,
CommentCommands::Delete {
project_id,
issue_id,
comment_id,
} => {
comments::delete_comment(client, &project_id, &issue_id, &comment_id, output_format)
.await
}
}
}
}
pub(super) fn truncate_str(s: &str, max_len: usize) -> String {
if s.len() <= max_len {
s.to_string()
} else {
format!("{}...", &s[..max_len - 3])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_truncate_str_short() {
assert_eq!(truncate_str("hello", 10), "hello");
}
#[test]
fn test_truncate_str_exact() {
assert_eq!(truncate_str("hello", 5), "hello");
}
#[test]
fn test_truncate_str_long() {
let result = truncate_str("hello world", 8);
assert_eq!(result, "hello...");
assert_eq!(result.len(), 8);
}
}