mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-10 03:59:31 +01:00
add pr change viewing commands
This commit is contained in:
parent
460ac72451
commit
6fd1976013
2 changed files with 172 additions and 3 deletions
|
@ -17,7 +17,7 @@ open = "5.0.0"
|
||||||
serde = { version = "1.0.170", features = ["derive"] }
|
serde = { version = "1.0.170", features = ["derive"] }
|
||||||
serde_json = "1.0.100"
|
serde_json = "1.0.100"
|
||||||
soft_assert = "0.1.1"
|
soft_assert = "0.1.1"
|
||||||
time = { version = "0.3.30", features = ["formatting"] }
|
time = { version = "0.3.30", features = ["formatting", "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"] }
|
||||||
|
|
173
src/prs.rs
173
src/prs.rs
|
@ -1,7 +1,10 @@
|
||||||
use clap::{Args, Subcommand};
|
use clap::{Args, Subcommand};
|
||||||
use eyre::OptionExt;
|
use eyre::OptionExt;
|
||||||
use forgejo_api::{
|
use forgejo_api::{
|
||||||
structs::{CreatePullRequestOption, MergePullRequestOption},
|
structs::{
|
||||||
|
CreatePullRequestOption, MergePullRequestOption, RepoGetPullRequestCommitsQuery,
|
||||||
|
RepoGetPullRequestFilesQuery,
|
||||||
|
},
|
||||||
Forgejo,
|
Forgejo,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,8 +110,24 @@ pub enum EditCommand {
|
||||||
#[derive(Subcommand, Clone, Debug)]
|
#[derive(Subcommand, Clone, Debug)]
|
||||||
pub enum ViewCommand {
|
pub enum ViewCommand {
|
||||||
Body,
|
Body,
|
||||||
Comment { idx: usize },
|
Comment {
|
||||||
|
idx: usize,
|
||||||
|
},
|
||||||
Comments,
|
Comments,
|
||||||
|
Diff {
|
||||||
|
/// Get the diff in patch format
|
||||||
|
#[clap(long, short)]
|
||||||
|
patch: bool,
|
||||||
|
/// View the diff in your text editor
|
||||||
|
#[clap(long, short)]
|
||||||
|
editor: bool,
|
||||||
|
},
|
||||||
|
Files,
|
||||||
|
Commits {
|
||||||
|
/// View one commit per line
|
||||||
|
#[clap(long, short)]
|
||||||
|
oneline: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrCommand {
|
impl PrCommand {
|
||||||
|
@ -133,6 +152,13 @@ impl PrCommand {
|
||||||
crate::issues::view_comment(&repo, &api, id, idx).await?
|
crate::issues::view_comment(&repo, &api, id, idx).await?
|
||||||
}
|
}
|
||||||
ViewCommand::Comments => crate::issues::view_comments(&repo, &api, id).await?,
|
ViewCommand::Comments => crate::issues::view_comments(&repo, &api, id).await?,
|
||||||
|
ViewCommand::Diff { patch, editor } => {
|
||||||
|
view_diff(&repo, &api, id, patch, editor).await?
|
||||||
|
}
|
||||||
|
ViewCommand::Files => view_pr_files(&repo, &api, id).await?,
|
||||||
|
ViewCommand::Commits { oneline } => {
|
||||||
|
view_pr_commits(&repo, &api, id, oneline).await?
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Search {
|
Search {
|
||||||
query,
|
query,
|
||||||
|
@ -308,3 +334,146 @@ async fn view_prs(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn view_diff(
|
||||||
|
repo: &RepoName,
|
||||||
|
api: &Forgejo,
|
||||||
|
pr: u64,
|
||||||
|
patch: bool,
|
||||||
|
editor: bool,
|
||||||
|
) -> eyre::Result<()> {
|
||||||
|
let diff_type = if patch { "patch" } else { "diff" };
|
||||||
|
let diff = api
|
||||||
|
.repo_download_pull_diff_or_patch(
|
||||||
|
repo.owner(),
|
||||||
|
repo.name(),
|
||||||
|
pr,
|
||||||
|
diff_type,
|
||||||
|
forgejo_api::structs::RepoDownloadPullDiffOrPatchQuery::default(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
if editor {
|
||||||
|
let mut view = diff.clone();
|
||||||
|
crate::editor(&mut view, Some(diff_type)).await?;
|
||||||
|
if view != diff {
|
||||||
|
println!("changes made to the diff will not persist");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("{diff}");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn view_pr_files(repo: &RepoName, api: &Forgejo, pr: u64) -> eyre::Result<()> {
|
||||||
|
let query = RepoGetPullRequestFilesQuery {
|
||||||
|
limit: Some(u32::MAX),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let (headers, files) = api
|
||||||
|
.repo_get_pull_request_files(repo.owner(), repo.name(), pr, query)
|
||||||
|
.await?;
|
||||||
|
let max_additions = files
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.additions.unwrap_or_default())
|
||||||
|
.max()
|
||||||
|
.unwrap_or_default();
|
||||||
|
let max_deletions = files
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.deletions.unwrap_or_default())
|
||||||
|
.max()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let additions_width = max_additions.checked_ilog10().unwrap_or_default() as usize + 1;
|
||||||
|
let deletions_width = max_deletions.checked_ilog10().unwrap_or_default() as usize + 1;
|
||||||
|
|
||||||
|
for file in files {
|
||||||
|
let name = file.filename.as_deref().unwrap_or("???");
|
||||||
|
let additions = file.additions.unwrap_or_default();
|
||||||
|
let deletions = file.deletions.unwrap_or_default();
|
||||||
|
println!("\x1b[92m+{additions:<additions_width$} \x1b[91m-{deletions:<deletions_width$}\x1b[0m {name}");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn view_pr_commits(
|
||||||
|
repo: &RepoName,
|
||||||
|
api: &Forgejo,
|
||||||
|
pr: u64,
|
||||||
|
oneline: bool,
|
||||||
|
) -> eyre::Result<()> {
|
||||||
|
let query = RepoGetPullRequestCommitsQuery {
|
||||||
|
limit: Some(u32::MAX),
|
||||||
|
files: Some(false),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let (_headers, commits) = api
|
||||||
|
.repo_get_pull_request_commits(repo.owner(), repo.name(), pr, query)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let max_additions = commits
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| x.stats.as_ref())
|
||||||
|
.map(|x| x.additions.unwrap_or_default())
|
||||||
|
.max()
|
||||||
|
.unwrap_or_default();
|
||||||
|
let max_deletions = commits
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| x.stats.as_ref())
|
||||||
|
.map(|x| x.deletions.unwrap_or_default())
|
||||||
|
.max()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let additions_width = max_additions.checked_ilog10().unwrap_or_default() as usize + 1;
|
||||||
|
let deletions_width = max_deletions.checked_ilog10().unwrap_or_default() as usize + 1;
|
||||||
|
|
||||||
|
for commit in commits {
|
||||||
|
let repo_commit = commit
|
||||||
|
.commit
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_eyre("commit does not have commit?")?;
|
||||||
|
|
||||||
|
let message = repo_commit.message.as_deref().unwrap_or("[no msg]");
|
||||||
|
let name = message.lines().next().unwrap_or(&message);
|
||||||
|
|
||||||
|
let sha = commit
|
||||||
|
.sha
|
||||||
|
.as_deref()
|
||||||
|
.ok_or_eyre("commit does not have sha")?;
|
||||||
|
let short_sha = &sha[..7];
|
||||||
|
|
||||||
|
let stats = commit
|
||||||
|
.stats
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_eyre("commit does not have stats")?;
|
||||||
|
let additions = stats.additions.unwrap_or_default();
|
||||||
|
let deletions = stats.deletions.unwrap_or_default();
|
||||||
|
|
||||||
|
if oneline {
|
||||||
|
println!("\x1b[33m{short_sha}\x1b[0m \x1b[92m+{additions:<additions_width$} \x1b[91m-{deletions:<deletions_width$}\x1b[0m {name}");
|
||||||
|
} else {
|
||||||
|
let author = repo_commit
|
||||||
|
.author
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_eyre("commit has no author")?;
|
||||||
|
let author_name = author.name.as_deref().ok_or_eyre("author has no name")?;
|
||||||
|
let author_email = author.email.as_deref().ok_or_eyre("author has no email")?;
|
||||||
|
let date = commit
|
||||||
|
.created
|
||||||
|
.as_ref()
|
||||||
|
.ok_or_eyre("commit as no creation date")?;
|
||||||
|
|
||||||
|
println!("\x1b[33mcommit {sha}\x1b[0m (\x1b[92m+{additions}\x1b[0m, \x1b[91m-{deletions}\x1b[0m)");
|
||||||
|
println!("Author: {author_name} <{author_email}>");
|
||||||
|
print!("Date: ");
|
||||||
|
let format = time::macros::format_description!("[weekday repr:short] [month repr:short] [day] [hour repr:24]:[minute]:[second] [year] [offset_hour sign:mandatory][offset_minute]");
|
||||||
|
date.format_into(&mut std::io::stdout().lock(), format)?;
|
||||||
|
println!();
|
||||||
|
println!();
|
||||||
|
for line in message.lines() {
|
||||||
|
println!(" {line}");
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue