mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-10 12:09:33 +01:00
Merge pull request 'add pr status
' (#88) from pr-status into main
Reviewed-on: https://codeberg.org/Cyborus/forgejo-cli/pulls/88
This commit is contained in:
commit
43765c77d7
3 changed files with 135 additions and 1 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -1186,6 +1186,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_threads"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.32.2"
|
version = "0.32.2"
|
||||||
|
@ -1868,7 +1877,9 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deranged",
|
"deranged",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"libc",
|
||||||
"num-conv",
|
"num-conv",
|
||||||
|
"num_threads",
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
"serde",
|
"serde",
|
||||||
"time-core",
|
"time-core",
|
||||||
|
|
|
@ -28,7 +28,7 @@ serde = { version = "1.0.170", features = ["derive"] }
|
||||||
serde_json = "1.0.100"
|
serde_json = "1.0.100"
|
||||||
sha256 = "1.5.0"
|
sha256 = "1.5.0"
|
||||||
soft_assert = "0.1.1"
|
soft_assert = "0.1.1"
|
||||||
time = { version = "0.3.30", features = ["formatting", "macros"] }
|
time = { version = "0.3.30", features = ["formatting", "local-offset", "macros"] }
|
||||||
tokio = { version = "1.29.1", features = ["full"] }
|
tokio = { version = "1.29.1", features = ["full"] }
|
||||||
url = "2.4.0"
|
url = "2.4.0"
|
||||||
uuid = { version = "1.5.0", features = ["v4"] }
|
uuid = { version = "1.5.0", features = ["v4"] }
|
||||||
|
|
123
src/prs.rs
123
src/prs.rs
|
@ -68,6 +68,11 @@ pub enum PrSubcommand {
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Option<ViewCommand>,
|
command: Option<ViewCommand>,
|
||||||
},
|
},
|
||||||
|
/// View the mergability and CI status of a pull request
|
||||||
|
Status {
|
||||||
|
/// The pull request to view.
|
||||||
|
id: Option<IssueId>,
|
||||||
|
},
|
||||||
/// Checkout a pull request in a new branch
|
/// Checkout a pull request in a new branch
|
||||||
Checkout {
|
Checkout {
|
||||||
/// The pull request to check out.
|
/// The pull request to check out.
|
||||||
|
@ -300,6 +305,7 @@ impl PrCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Status { id } => view_pr_status(&repo, &api, id.map(|id| id.number)).await?,
|
||||||
Search {
|
Search {
|
||||||
query,
|
query,
|
||||||
labels,
|
labels,
|
||||||
|
@ -351,6 +357,7 @@ impl PrCommand {
|
||||||
Search { repo, .. } | Create { repo, .. } => repo.as_ref(),
|
Search { repo, .. } | Create { repo, .. } => repo.as_ref(),
|
||||||
Checkout { .. } => None,
|
Checkout { .. } => None,
|
||||||
View { id: pr, .. }
|
View { id: pr, .. }
|
||||||
|
| Status { id: pr, .. }
|
||||||
| Comment { pr, .. }
|
| Comment { pr, .. }
|
||||||
| Edit { pr, .. }
|
| Edit { pr, .. }
|
||||||
| Close { pr, .. }
|
| Close { pr, .. }
|
||||||
|
@ -373,6 +380,7 @@ impl PrCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
View { id: pr, .. }
|
View { id: pr, .. }
|
||||||
|
| Status { id: pr, .. }
|
||||||
| Comment { pr, .. }
|
| Comment { pr, .. }
|
||||||
| Edit { pr, .. }
|
| Edit { pr, .. }
|
||||||
| Close { pr, .. }
|
| Close { pr, .. }
|
||||||
|
@ -578,6 +586,121 @@ fn darken(r: u8, g: u8, b: u8) -> (u8, u8, u8) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn view_pr_status(repo: &RepoName, api: &Forgejo, id: Option<u64>) -> eyre::Result<()> {
|
||||||
|
let pr = try_get_pr(repo, api, id).await?;
|
||||||
|
|
||||||
|
let SpecialRender {
|
||||||
|
bright_magenta,
|
||||||
|
bright_red,
|
||||||
|
bright_green,
|
||||||
|
yellow,
|
||||||
|
light_grey,
|
||||||
|
dash,
|
||||||
|
bullet,
|
||||||
|
reset,
|
||||||
|
..
|
||||||
|
} = *crate::special_render();
|
||||||
|
|
||||||
|
if pr.merged.ok_or_eyre("pr merge status unknown")? {
|
||||||
|
let merged_by = pr.merged_by.ok_or_eyre("pr not merged by anyone")?;
|
||||||
|
let merged_by = merged_by
|
||||||
|
.login
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_eyre("pr merger does not have login")?;
|
||||||
|
let merged_at = pr.merged_at.ok_or_eyre("pr does not have merge date")?;
|
||||||
|
let date_format = time::macros::format_description!(
|
||||||
|
"on [month repr:long] [day], [year], at [hour repr:12]:[minute] [period]"
|
||||||
|
);
|
||||||
|
let tz_format = time::macros::format_description!(
|
||||||
|
"[offset_hour padding:zero sign:mandatory]:[offset_minute]"
|
||||||
|
);
|
||||||
|
let (merged_at, show_tz) = if let Ok(local_offset) = time::UtcOffset::current_local_offset()
|
||||||
|
{
|
||||||
|
let merged_at = merged_at.to_offset(local_offset);
|
||||||
|
(merged_at, false)
|
||||||
|
} else {
|
||||||
|
(merged_at, true)
|
||||||
|
};
|
||||||
|
print!(
|
||||||
|
"{bright_magenta}Merged{reset} by {merged_by} {}",
|
||||||
|
merged_at.format(date_format)?
|
||||||
|
);
|
||||||
|
if show_tz {
|
||||||
|
print!("{}", merged_at.format(tz_format)?);
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
} else {
|
||||||
|
let pr_number = pr.number.ok_or_eyre("pr does not have number")?;
|
||||||
|
let query = forgejo_api::structs::RepoGetPullRequestCommitsQuery {
|
||||||
|
page: None,
|
||||||
|
limit: Some(u32::MAX),
|
||||||
|
verification: Some(false),
|
||||||
|
files: Some(false),
|
||||||
|
};
|
||||||
|
let (_commit_headers, commits) = api
|
||||||
|
.repo_get_pull_request_commits(repo.owner(), repo.name(), pr_number, query)
|
||||||
|
.await?;
|
||||||
|
let latest_commit = commits
|
||||||
|
.iter()
|
||||||
|
.max_by_key(|x| x.created)
|
||||||
|
.ok_or_eyre("no commits in pr")?;
|
||||||
|
let sha = latest_commit
|
||||||
|
.sha
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_eyre("commit does not have sha")?;
|
||||||
|
let query = forgejo_api::structs::RepoGetCombinedStatusByRefQuery {
|
||||||
|
page: None,
|
||||||
|
limit: Some(u32::MAX),
|
||||||
|
};
|
||||||
|
let combined_status = api
|
||||||
|
.repo_get_combined_status_by_ref(repo.owner(), repo.name(), sha, query)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let state = pr.state.ok_or_eyre("pr does not have state")?;
|
||||||
|
let is_draft = pr.title.as_deref().is_some_and(|s| s.starts_with("WIP:"));
|
||||||
|
match state {
|
||||||
|
StateType::Open => {
|
||||||
|
if is_draft {
|
||||||
|
println!("{light_grey}Draft{reset} {dash} Can't merge draft PR")
|
||||||
|
} else {
|
||||||
|
print!("{bright_green}Open{reset} {dash} ");
|
||||||
|
let mergable = pr.mergeable.ok_or_eyre("pr does not have mergable")?;
|
||||||
|
if mergable {
|
||||||
|
println!("Can be merged");
|
||||||
|
} else {
|
||||||
|
println!("{bright_red}Merge conflicts{reset}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateType::Closed => println!("{bright_red}Closed{reset} {dash} Reopen to merge"),
|
||||||
|
}
|
||||||
|
|
||||||
|
let commit_statuses = combined_status
|
||||||
|
.statuses
|
||||||
|
.ok_or_eyre("combined status does not have status list")?;
|
||||||
|
for status in commit_statuses {
|
||||||
|
let state = status
|
||||||
|
.status
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_eyre("status does not have status")?;
|
||||||
|
let context = status
|
||||||
|
.context
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_eyre("status does not have context")?;
|
||||||
|
print!("{bullet} ");
|
||||||
|
match state {
|
||||||
|
"success" => print!("{bright_green}Success{reset}"),
|
||||||
|
"pending" => print!("{yellow}Pending{reset}"),
|
||||||
|
"failure" => print!("{bright_red}Failure{reset}"),
|
||||||
|
_ => eyre::bail!("invalid status"),
|
||||||
|
};
|
||||||
|
println!(" {dash} {context}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn edit_pr_labels(
|
async fn edit_pr_labels(
|
||||||
repo: &RepoName,
|
repo: &RepoName,
|
||||||
api: &Forgejo,
|
api: &Forgejo,
|
||||||
|
|
Loading…
Reference in a new issue