Prepare Gotcha 1.0 for release
This commit is contained in:
258
crates/cli/src/work_items/output.rs
Normal file
258
crates/cli/src/work_items/output.rs
Normal file
@@ -0,0 +1,258 @@
|
||||
use gotcha_gitea::models::{
|
||||
ChangedFile, Comment, Commit, Issue, Milestone, PullRequest, PullReview,
|
||||
};
|
||||
use gotcha_gitea::pull_state;
|
||||
|
||||
use crate::print_table;
|
||||
|
||||
pub(super) fn print_issues(issues: &[Issue]) {
|
||||
print_table(
|
||||
&[
|
||||
("INDEX", 8),
|
||||
("STATE", 10),
|
||||
("TITLE", 60),
|
||||
("MILESTONE", 30),
|
||||
("LABELS", 30),
|
||||
],
|
||||
issues
|
||||
.iter()
|
||||
.map(|issue| {
|
||||
vec![
|
||||
issue.number.unwrap_or_default().to_string(),
|
||||
issue.state.as_deref().unwrap_or("unknown").into(),
|
||||
one_line(issue.title.as_deref().unwrap_or("")).into(),
|
||||
issue
|
||||
.milestone
|
||||
.as_deref()
|
||||
.and_then(|milestone| milestone.title.as_deref())
|
||||
.unwrap_or("-")
|
||||
.into(),
|
||||
issue_labels(issue),
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn print_issue(issue: &Issue) {
|
||||
println!(
|
||||
"#{} [{}] {}",
|
||||
issue.number.unwrap_or_default(),
|
||||
issue.state.as_deref().unwrap_or("unknown"),
|
||||
issue.title.as_deref().unwrap_or("")
|
||||
);
|
||||
field("url", issue.html_url.as_deref());
|
||||
field(
|
||||
"author",
|
||||
issue.user.as_deref().and_then(|user| user.login.as_deref()),
|
||||
);
|
||||
let milestone = issue
|
||||
.milestone
|
||||
.as_deref()
|
||||
.and_then(|milestone| milestone.title.as_deref());
|
||||
field("milestone", milestone);
|
||||
let labels = issue_labels(issue);
|
||||
field("labels", (!labels.is_empty()).then_some(labels.as_str()));
|
||||
let assignees = issue
|
||||
.assignees
|
||||
.as_deref()
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.filter_map(|user| user.login.as_deref())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
field(
|
||||
"assignees",
|
||||
(!assignees.is_empty()).then_some(assignees.as_str()),
|
||||
);
|
||||
field("due", issue.due_date.as_deref());
|
||||
field("created", issue.created_at.as_deref());
|
||||
field("updated", issue.updated_at.as_deref());
|
||||
println!("comments: {}", issue.comments.unwrap_or_default());
|
||||
body(issue.body.as_deref());
|
||||
}
|
||||
|
||||
fn issue_labels(issue: &Issue) -> String {
|
||||
issue
|
||||
.labels
|
||||
.as_deref()
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.filter_map(|label| label.name.as_deref())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
}
|
||||
|
||||
pub(super) fn print_comments(comments: &[Comment]) {
|
||||
for comment in comments {
|
||||
println!(
|
||||
"{} · {}",
|
||||
comment
|
||||
.user
|
||||
.as_deref()
|
||||
.and_then(|user| user.login.as_deref())
|
||||
.unwrap_or("unknown"),
|
||||
comment.created_at.as_deref().unwrap_or("-")
|
||||
);
|
||||
body(comment.body.as_deref());
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn print_milestones(milestones: &[Milestone]) {
|
||||
print_table(
|
||||
&[
|
||||
("ID", 8),
|
||||
("STATE", 10),
|
||||
("TITLE", 60),
|
||||
("DUE", 25),
|
||||
("OPEN/CLOSED", 12),
|
||||
],
|
||||
milestones
|
||||
.iter()
|
||||
.map(|milestone| {
|
||||
vec![
|
||||
milestone.id.unwrap_or_default().to_string(),
|
||||
milestone.state.as_deref().unwrap_or("unknown").into(),
|
||||
one_line(milestone.title.as_deref().unwrap_or("")).into(),
|
||||
milestone.due_on.as_deref().unwrap_or("-").into(),
|
||||
format!(
|
||||
"{}/{}",
|
||||
milestone.open_issues.unwrap_or_default(),
|
||||
milestone.closed_issues.unwrap_or_default()
|
||||
),
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn print_milestone(milestone: &Milestone) {
|
||||
println!(
|
||||
"{} [{}] {}",
|
||||
milestone.id.unwrap_or_default(),
|
||||
milestone.state.as_deref().unwrap_or("unknown"),
|
||||
milestone.title.as_deref().unwrap_or("")
|
||||
);
|
||||
field("due", milestone.due_on.as_deref());
|
||||
println!(
|
||||
"issues: {} open, {} closed",
|
||||
milestone.open_issues.unwrap_or_default(),
|
||||
milestone.closed_issues.unwrap_or_default()
|
||||
);
|
||||
body(milestone.description.as_deref());
|
||||
}
|
||||
|
||||
pub(super) fn print_pulls(pulls: &[PullRequest]) {
|
||||
print_table(
|
||||
&[("INDEX", 8), ("STATE", 10), ("TITLE", 70), ("UPDATED", 25)],
|
||||
pulls
|
||||
.iter()
|
||||
.map(|pull| {
|
||||
vec![
|
||||
pull.number.unwrap_or_default().to_string(),
|
||||
pull.state.as_deref().unwrap_or("unknown").into(),
|
||||
one_line(pull.title.as_deref().unwrap_or("")).into(),
|
||||
pull.updated_at.as_deref().unwrap_or("-").into(),
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn print_pull(pull: &PullRequest) {
|
||||
println!(
|
||||
"#{} [{}] {}",
|
||||
pull.number.unwrap_or_default(),
|
||||
pull_state(pull),
|
||||
pull.title.as_deref().unwrap_or("")
|
||||
);
|
||||
field("url", pull.html_url.as_deref());
|
||||
field(
|
||||
"author",
|
||||
pull.user.as_deref().and_then(|user| user.login.as_deref()),
|
||||
);
|
||||
field("updated", pull.updated_at.as_deref());
|
||||
println!("mergeable: {}", pull.mergeable.unwrap_or(false));
|
||||
body(pull.body.as_deref());
|
||||
}
|
||||
|
||||
pub(super) fn print_commits(commits: &[Commit]) {
|
||||
print_table(
|
||||
&[("SHA", 40), ("MESSAGE", 80)],
|
||||
commits
|
||||
.iter()
|
||||
.map(|commit| {
|
||||
vec![
|
||||
commit.sha.as_deref().unwrap_or("unknown").into(),
|
||||
one_line(
|
||||
commit
|
||||
.commit
|
||||
.as_deref()
|
||||
.and_then(|commit| commit.message.as_deref())
|
||||
.unwrap_or(""),
|
||||
)
|
||||
.into(),
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn print_files(files: &[ChangedFile]) {
|
||||
print_table(
|
||||
&[("STATUS", 12), ("CHANGES", 10), ("FILE", 90)],
|
||||
files
|
||||
.iter()
|
||||
.map(|file| {
|
||||
vec![
|
||||
file.status.as_deref().unwrap_or("unknown").into(),
|
||||
file.changes.unwrap_or_default().to_string(),
|
||||
file.filename.as_deref().unwrap_or("").into(),
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn print_reviews(reviews: &[PullReview]) {
|
||||
print_table(
|
||||
&[
|
||||
("ID", 12),
|
||||
("STATE", 20),
|
||||
("REVIEWER", 25),
|
||||
("SUBMITTED", 25),
|
||||
],
|
||||
reviews
|
||||
.iter()
|
||||
.map(|review| {
|
||||
vec![
|
||||
review.id.unwrap_or_default().to_string(),
|
||||
review.state.as_deref().unwrap_or("unknown").into(),
|
||||
review
|
||||
.user
|
||||
.as_deref()
|
||||
.and_then(|user| user.login.as_deref())
|
||||
.unwrap_or("unknown")
|
||||
.into(),
|
||||
review.submitted_at.as_deref().unwrap_or("-").into(),
|
||||
]
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
fn field(name: &str, value: Option<&str>) {
|
||||
if let Some(value) = value.filter(|value| !value.is_empty()) {
|
||||
println!("{name}: {value}");
|
||||
}
|
||||
}
|
||||
|
||||
fn body(value: Option<&str>) {
|
||||
if let Some(value) = value.filter(|value| !value.is_empty()) {
|
||||
println!("\n{value}");
|
||||
}
|
||||
}
|
||||
|
||||
fn one_line(value: &str) -> &str {
|
||||
value.lines().next().unwrap_or_default()
|
||||
}
|
||||
Reference in New Issue
Block a user