mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-12 21:19:49 +01:00
improve specifying repo in issue and pr commands
This commit is contained in:
parent
c30f7ad27f
commit
619a17a9c6
2 changed files with 209 additions and 61 deletions
125
src/issues.rs
125
src/issues.rs
|
@ -1,3 +1,5 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use clap::{Args, Subcommand};
|
use clap::{Args, Subcommand};
|
||||||
use eyre::{eyre, OptionExt};
|
use eyre::{eyre, OptionExt};
|
||||||
use forgejo_api::structs::{
|
use forgejo_api::structs::{
|
||||||
|
@ -11,8 +13,6 @@ use crate::repo::{RepoInfo, RepoName};
|
||||||
pub struct IssueCommand {
|
pub struct IssueCommand {
|
||||||
#[clap(long, short = 'R')]
|
#[clap(long, short = 'R')]
|
||||||
remote: Option<String>,
|
remote: Option<String>,
|
||||||
#[clap(long, short)]
|
|
||||||
repo: Option<String>,
|
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: IssueSubcommand,
|
command: IssueSubcommand,
|
||||||
}
|
}
|
||||||
|
@ -23,22 +23,26 @@ pub enum IssueSubcommand {
|
||||||
title: String,
|
title: String,
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
body: Option<String>,
|
body: Option<String>,
|
||||||
|
#[clap(long, short)]
|
||||||
|
repo: Option<String>,
|
||||||
},
|
},
|
||||||
Edit {
|
Edit {
|
||||||
issue: u64,
|
issue: IssueId,
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: EditCommand,
|
command: EditCommand,
|
||||||
},
|
},
|
||||||
Comment {
|
Comment {
|
||||||
issue: u64,
|
issue: IssueId,
|
||||||
body: Option<String>,
|
body: Option<String>,
|
||||||
},
|
},
|
||||||
Close {
|
Close {
|
||||||
issue: u64,
|
issue: IssueId,
|
||||||
#[clap(long, short)]
|
#[clap(long, short)]
|
||||||
with_msg: Option<Option<String>>,
|
with_msg: Option<Option<String>>,
|
||||||
},
|
},
|
||||||
Search {
|
Search {
|
||||||
|
#[clap(long, short)]
|
||||||
|
repo: Option<String>,
|
||||||
query: Option<String>,
|
query: Option<String>,
|
||||||
#[clap(long, short)]
|
#[clap(long, short)]
|
||||||
labels: Option<String>,
|
labels: Option<String>,
|
||||||
|
@ -50,15 +54,36 @@ pub enum IssueSubcommand {
|
||||||
state: Option<State>,
|
state: Option<State>,
|
||||||
},
|
},
|
||||||
View {
|
View {
|
||||||
id: u64,
|
id: IssueId,
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Option<ViewCommand>,
|
command: Option<ViewCommand>,
|
||||||
},
|
},
|
||||||
Browse {
|
Browse {
|
||||||
id: Option<u64>,
|
id: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct IssueId {
|
||||||
|
pub repo: Option<String>,
|
||||||
|
pub number: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for IssueId {
|
||||||
|
type Err = std::num::ParseIntError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let (repo, number) = match s.rsplit_once("#") {
|
||||||
|
Some((repo, number)) => (Some(repo.to_owned()), number),
|
||||||
|
None => (None, s),
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
repo,
|
||||||
|
number: number.parse()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(clap::ValueEnum, Clone, Copy, Debug)]
|
#[derive(clap::ValueEnum, Clone, Copy, Debug)]
|
||||||
pub enum State {
|
pub enum State {
|
||||||
Open,
|
Open,
|
||||||
|
@ -98,19 +123,22 @@ pub enum ViewCommand {
|
||||||
impl IssueCommand {
|
impl IssueCommand {
|
||||||
pub async fn run(self, keys: &crate::KeyInfo, host_name: Option<&str>) -> eyre::Result<()> {
|
pub async fn run(self, keys: &crate::KeyInfo, host_name: Option<&str>) -> eyre::Result<()> {
|
||||||
use IssueSubcommand::*;
|
use IssueSubcommand::*;
|
||||||
let repo = RepoInfo::get_current(host_name, self.repo.as_deref(), self.remote.as_deref())?;
|
let repo = RepoInfo::get_current(host_name, self.repo(), self.remote.as_deref())?;
|
||||||
let api = keys.get_api(repo.host_url())?;
|
let api = keys.get_api(repo.host_url())?;
|
||||||
let repo = repo
|
let repo = repo.name().ok_or_else(|| self.no_repo_error())?;
|
||||||
.name()
|
|
||||||
.ok_or_eyre("couldn't get repo name, try specifying with --repo")?;
|
|
||||||
match self.command {
|
match self.command {
|
||||||
Create { title, body } => create_issue(&repo, &api, title, body).await?,
|
Create {
|
||||||
|
repo: _,
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
} => create_issue(&repo, &api, title, body).await?,
|
||||||
View { id, command } => match command.unwrap_or(ViewCommand::Body) {
|
View { id, command } => match command.unwrap_or(ViewCommand::Body) {
|
||||||
ViewCommand::Body => view_issue(&repo, &api, id).await?,
|
ViewCommand::Body => view_issue(&repo, &api, id.number).await?,
|
||||||
ViewCommand::Comment { idx } => view_comment(&repo, &api, id, idx).await?,
|
ViewCommand::Comment { idx } => view_comment(&repo, &api, id.number, idx).await?,
|
||||||
ViewCommand::Comments => view_comments(&repo, &api, id).await?,
|
ViewCommand::Comments => view_comments(&repo, &api, id.number).await?,
|
||||||
},
|
},
|
||||||
Search {
|
Search {
|
||||||
|
repo: _,
|
||||||
query,
|
query,
|
||||||
labels,
|
labels,
|
||||||
creator,
|
creator,
|
||||||
|
@ -119,19 +147,74 @@ impl IssueCommand {
|
||||||
} => view_issues(&repo, &api, query, labels, creator, assignee, state).await?,
|
} => view_issues(&repo, &api, query, labels, creator, assignee, state).await?,
|
||||||
Edit { issue, command } => match command {
|
Edit { issue, command } => match command {
|
||||||
EditCommand::Title { new_title } => {
|
EditCommand::Title { new_title } => {
|
||||||
edit_title(&repo, &api, issue, new_title).await?
|
edit_title(&repo, &api, issue.number, new_title).await?
|
||||||
|
}
|
||||||
|
EditCommand::Body { new_body } => {
|
||||||
|
edit_body(&repo, &api, issue.number, new_body).await?
|
||||||
}
|
}
|
||||||
EditCommand::Body { new_body } => edit_body(&repo, &api, issue, new_body).await?,
|
|
||||||
EditCommand::Comment { idx, new_body } => {
|
EditCommand::Comment { idx, new_body } => {
|
||||||
edit_comment(&repo, &api, issue, idx, new_body).await?
|
edit_comment(&repo, &api, issue.number, idx, new_body).await?
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Close { issue, with_msg } => close_issue(&repo, &api, issue, with_msg).await?,
|
Close { issue, with_msg } => close_issue(&repo, &api, issue.number, with_msg).await?,
|
||||||
Browse { id } => browse_issue(&repo, &api, id).await?,
|
Browse { id } => {
|
||||||
Comment { issue, body } => add_comment(&repo, &api, issue, body).await?,
|
let number = id.as_ref().and_then(|s| {
|
||||||
|
let num_s = s.rsplit_once("#").map(|(_, b)| b).unwrap_or(s);
|
||||||
|
num_s.parse::<u64>().ok()
|
||||||
|
});
|
||||||
|
browse_issue(&repo, &api, number).await?
|
||||||
|
}
|
||||||
|
Comment { issue, body } => add_comment(&repo, &api, issue.number, body).await?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn repo(&self) -> Option<&str> {
|
||||||
|
use IssueSubcommand::*;
|
||||||
|
match &self.command {
|
||||||
|
Create { repo, .. } | Search { repo, .. } => repo.as_deref(),
|
||||||
|
View { id: issue, .. }
|
||||||
|
| Edit { issue, .. }
|
||||||
|
| Close { issue, .. }
|
||||||
|
| Comment { issue, .. } => issue.repo.as_deref(),
|
||||||
|
Browse { id, .. } => id.as_ref().and_then(|s| {
|
||||||
|
let repo = s.rsplit_once("#").map(|(a, _)| a).unwrap_or(s);
|
||||||
|
// Don't treat a lone issue number as a repo name
|
||||||
|
if repo.parse::<u64>().is_ok() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(repo)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn no_repo_error(&self) -> eyre::Error {
|
||||||
|
use IssueSubcommand::*;
|
||||||
|
match &self.command {
|
||||||
|
Create { repo, .. } | Search { repo, .. } => {
|
||||||
|
eyre::eyre!("can't figure what repo to access, try specifying with `--repo`")
|
||||||
|
}
|
||||||
|
View { id: issue, .. }
|
||||||
|
| Edit { issue, .. }
|
||||||
|
| Close { issue, .. }
|
||||||
|
| Comment { issue, .. } => eyre::eyre!(
|
||||||
|
"can't figure out what repo to access, try specifying with `{{owner}}/{{repo}}#{}`",
|
||||||
|
issue.number
|
||||||
|
),
|
||||||
|
Browse { id, .. } => {
|
||||||
|
let number = id.as_ref().and_then(|s| {
|
||||||
|
let num_s = s.rsplit_once("#").map(|(_, b)| b).unwrap_or(s);
|
||||||
|
num_s.parse::<u64>().ok()
|
||||||
|
});
|
||||||
|
if let Some(number) = number {
|
||||||
|
eyre::eyre!("can't figure out what repo to access, try specifying with `{{owner}}/{{repo}}#{}`", number)
|
||||||
|
} else {
|
||||||
|
eyre::eyre!("can't figure out what repo to access, try specifying with `{{owner}}/{{repo}}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_issue(
|
async fn create_issue(
|
||||||
|
|
145
src/prs.rs
145
src/prs.rs
|
@ -11,6 +11,7 @@ use forgejo_api::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
issues::IssueId,
|
||||||
repo::{RepoInfo, RepoName},
|
repo::{RepoInfo, RepoName},
|
||||||
SpecialRender,
|
SpecialRender,
|
||||||
};
|
};
|
||||||
|
@ -20,9 +21,6 @@ pub struct PrCommand {
|
||||||
/// The git remote to operate on.
|
/// The git remote to operate on.
|
||||||
#[clap(long, short = 'R')]
|
#[clap(long, short = 'R')]
|
||||||
remote: Option<String>,
|
remote: Option<String>,
|
||||||
/// The name of the remote repository to operate on.
|
|
||||||
#[clap(long, short)]
|
|
||||||
repo: Option<String>,
|
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: PrSubcommand,
|
command: PrSubcommand,
|
||||||
}
|
}
|
||||||
|
@ -40,6 +38,9 @@ pub enum PrSubcommand {
|
||||||
assignee: Option<String>,
|
assignee: Option<String>,
|
||||||
#[clap(long, short)]
|
#[clap(long, short)]
|
||||||
state: Option<crate::issues::State>,
|
state: Option<crate::issues::State>,
|
||||||
|
/// The repo to search in
|
||||||
|
#[clap(long, short)]
|
||||||
|
repo: Option<String>,
|
||||||
},
|
},
|
||||||
/// Create a new pull request
|
/// Create a new pull request
|
||||||
Create {
|
Create {
|
||||||
|
@ -56,11 +57,14 @@ pub enum PrSubcommand {
|
||||||
/// Leaving this out will open your editor.
|
/// Leaving this out will open your editor.
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
body: Option<String>,
|
body: Option<String>,
|
||||||
|
/// The repo to create this issue on
|
||||||
|
#[clap(long, short)]
|
||||||
|
repo: Option<String>,
|
||||||
},
|
},
|
||||||
/// View the contents of a pull request
|
/// View the contents of a pull request
|
||||||
View {
|
View {
|
||||||
/// The pull request to view.
|
/// The pull request to view.
|
||||||
id: u64,
|
id: IssueId,
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Option<ViewCommand>,
|
command: Option<ViewCommand>,
|
||||||
},
|
},
|
||||||
|
@ -79,7 +83,7 @@ pub enum PrSubcommand {
|
||||||
/// Add a comment on a pull request
|
/// Add a comment on a pull request
|
||||||
Comment {
|
Comment {
|
||||||
/// The pull request to comment on.
|
/// The pull request to comment on.
|
||||||
pr: u64,
|
pr: IssueId,
|
||||||
/// The text content of the comment.
|
/// The text content of the comment.
|
||||||
///
|
///
|
||||||
/// Not including this in the command will open your editor.
|
/// Not including this in the command will open your editor.
|
||||||
|
@ -88,14 +92,14 @@ pub enum PrSubcommand {
|
||||||
/// Edit the contents of a pull request
|
/// Edit the contents of a pull request
|
||||||
Edit {
|
Edit {
|
||||||
/// The pull request to edit.
|
/// The pull request to edit.
|
||||||
pr: u64,
|
pr: IssueId,
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: EditCommand,
|
command: EditCommand,
|
||||||
},
|
},
|
||||||
/// Close a pull request, without merging.
|
/// Close a pull request, without merging.
|
||||||
Close {
|
Close {
|
||||||
/// The pull request to close.
|
/// The pull request to close.
|
||||||
pr: u64,
|
pr: IssueId,
|
||||||
/// A comment to add before closing.
|
/// A comment to add before closing.
|
||||||
///
|
///
|
||||||
/// Adding without an argument will open your editor
|
/// Adding without an argument will open your editor
|
||||||
|
@ -105,7 +109,7 @@ pub enum PrSubcommand {
|
||||||
/// Merge a pull request
|
/// Merge a pull request
|
||||||
Merge {
|
Merge {
|
||||||
/// The pull request to merge.
|
/// The pull request to merge.
|
||||||
pr: u64,
|
pr: IssueId,
|
||||||
/// The merge style to use.
|
/// The merge style to use.
|
||||||
#[clap(long, short)]
|
#[clap(long, short)]
|
||||||
method: Option<MergeMethod>,
|
method: Option<MergeMethod>,
|
||||||
|
@ -118,7 +122,7 @@ pub enum PrSubcommand {
|
||||||
/// The pull request to open in your browser.
|
/// The pull request to open in your browser.
|
||||||
///
|
///
|
||||||
/// Leave this out to open the list of PRs.
|
/// Leave this out to open the list of PRs.
|
||||||
id: Option<u64>,
|
id: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,32 +245,35 @@ pub enum ViewCommand {
|
||||||
impl PrCommand {
|
impl PrCommand {
|
||||||
pub async fn run(self, keys: &crate::KeyInfo, host_name: Option<&str>) -> eyre::Result<()> {
|
pub async fn run(self, keys: &crate::KeyInfo, host_name: Option<&str>) -> eyre::Result<()> {
|
||||||
use PrSubcommand::*;
|
use PrSubcommand::*;
|
||||||
let repo = RepoInfo::get_current(host_name, self.repo.as_deref(), self.remote.as_deref())?;
|
let repo = RepoInfo::get_current(host_name, self.repo(), self.remote.as_deref())?;
|
||||||
let api = keys.get_api(repo.host_url())?;
|
let api = keys.get_api(repo.host_url())?;
|
||||||
let repo = repo
|
let repo = repo.name().ok_or_else(|| self.no_repo_error())?;
|
||||||
.name()
|
|
||||||
.ok_or_eyre("couldn't get repo name, try specifying with --repo")?;
|
|
||||||
match self.command {
|
match self.command {
|
||||||
Create {
|
Create {
|
||||||
title,
|
title,
|
||||||
base,
|
base,
|
||||||
head,
|
head,
|
||||||
body,
|
body,
|
||||||
|
repo: _,
|
||||||
} => create_pr(&repo, &api, title, base, head, body).await?,
|
} => create_pr(&repo, &api, title, base, head, body).await?,
|
||||||
Merge { pr, method, delete } => merge_pr(&repo, &api, pr, method, delete).await?,
|
Merge { pr, method, delete } => {
|
||||||
|
merge_pr(&repo, &api, pr.number, method, delete).await?
|
||||||
|
}
|
||||||
View { id, command } => match command.unwrap_or(ViewCommand::Body) {
|
View { id, command } => match command.unwrap_or(ViewCommand::Body) {
|
||||||
ViewCommand::Body => view_pr(&repo, &api, id).await?,
|
ViewCommand::Body => view_pr(&repo, &api, id.number).await?,
|
||||||
ViewCommand::Comment { idx } => {
|
ViewCommand::Comment { idx } => {
|
||||||
crate::issues::view_comment(&repo, &api, id, idx).await?
|
crate::issues::view_comment(&repo, &api, id.number, idx).await?
|
||||||
}
|
}
|
||||||
ViewCommand::Comments => crate::issues::view_comments(&repo, &api, id).await?,
|
ViewCommand::Comments => {
|
||||||
ViewCommand::Labels => view_pr_labels(&repo, &api, id).await?,
|
crate::issues::view_comments(&repo, &api, id.number).await?
|
||||||
|
}
|
||||||
|
ViewCommand::Labels => view_pr_labels(&repo, &api, id.number).await?,
|
||||||
ViewCommand::Diff { patch, editor } => {
|
ViewCommand::Diff { patch, editor } => {
|
||||||
view_diff(&repo, &api, id, patch, editor).await?
|
view_diff(&repo, &api, id.number, patch, editor).await?
|
||||||
}
|
}
|
||||||
ViewCommand::Files => view_pr_files(&repo, &api, id).await?,
|
ViewCommand::Files => view_pr_files(&repo, &api, id.number).await?,
|
||||||
ViewCommand::Commits { oneline } => {
|
ViewCommand::Commits { oneline } => {
|
||||||
view_pr_commits(&repo, &api, id, oneline).await?
|
view_pr_commits(&repo, &api, id.number, oneline).await?
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Search {
|
Search {
|
||||||
|
@ -275,28 +282,96 @@ impl PrCommand {
|
||||||
creator,
|
creator,
|
||||||
assignee,
|
assignee,
|
||||||
state,
|
state,
|
||||||
|
repo: _,
|
||||||
} => view_prs(&repo, &api, query, labels, creator, assignee, state).await?,
|
} => view_prs(&repo, &api, query, labels, creator, assignee, state).await?,
|
||||||
Edit { pr, command } => match command {
|
Edit { pr, command } => match command {
|
||||||
EditCommand::Title { new_title } => {
|
EditCommand::Title { new_title } => {
|
||||||
crate::issues::edit_title(&repo, &api, pr, new_title).await?
|
crate::issues::edit_title(&repo, &api, pr.number, new_title).await?
|
||||||
}
|
}
|
||||||
EditCommand::Body { new_body } => {
|
EditCommand::Body { new_body } => {
|
||||||
crate::issues::edit_body(&repo, &api, pr, new_body).await?
|
crate::issues::edit_body(&repo, &api, pr.number, new_body).await?
|
||||||
}
|
}
|
||||||
EditCommand::Comment { idx, new_body } => {
|
EditCommand::Comment { idx, new_body } => {
|
||||||
crate::issues::edit_comment(&repo, &api, pr, idx, new_body).await?
|
crate::issues::edit_comment(&repo, &api, pr.number, idx, new_body).await?
|
||||||
|
}
|
||||||
|
EditCommand::Labels { add, rm } => {
|
||||||
|
edit_pr_labels(&repo, &api, pr.number, add, rm).await?
|
||||||
}
|
}
|
||||||
EditCommand::Labels { add, rm } => edit_pr_labels(&repo, &api, pr, add, rm).await?,
|
|
||||||
},
|
},
|
||||||
Close { pr, with_msg } => crate::issues::close_issue(&repo, &api, pr, with_msg).await?,
|
Close { pr, with_msg } => {
|
||||||
Checkout { pr, branch_name } => {
|
crate::issues::close_issue(&repo, &api, pr.number, with_msg).await?
|
||||||
checkout_pr(&repo, &api, pr, self.repo.is_some(), branch_name).await?
|
}
|
||||||
|
Checkout { pr, branch_name } => checkout_pr(&repo, &api, pr, branch_name).await?,
|
||||||
|
Browse { id } => {
|
||||||
|
let number = id.as_ref().and_then(|s| {
|
||||||
|
let num_s = s.rsplit_once("#").map(|(_, b)| b).unwrap_or(s);
|
||||||
|
num_s.parse::<u64>().ok()
|
||||||
|
});
|
||||||
|
browse_pr(&repo, &api, number).await?
|
||||||
|
}
|
||||||
|
Comment { pr, body } => {
|
||||||
|
crate::issues::add_comment(&repo, &api, pr.number, body).await?
|
||||||
}
|
}
|
||||||
Browse { id } => browse_pr(&repo, &api, id).await?,
|
|
||||||
Comment { pr, body } => crate::issues::add_comment(&repo, &api, pr, body).await?,
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn repo(&self) -> Option<&str> {
|
||||||
|
use PrSubcommand::*;
|
||||||
|
match &self.command {
|
||||||
|
Search { repo, .. } | Create { repo, .. } => repo.as_deref(),
|
||||||
|
Checkout { .. } => None,
|
||||||
|
View { id: pr, .. }
|
||||||
|
| Comment { pr, .. }
|
||||||
|
| Edit { pr, .. }
|
||||||
|
| Close { pr, .. }
|
||||||
|
| Merge { pr, .. } => pr.repo.as_deref(),
|
||||||
|
Browse { id } => id.as_ref().and_then(|s| {
|
||||||
|
let repo = s.rsplit_once("#").map(|(a, _)| a).unwrap_or(s);
|
||||||
|
// Don't treat a lone PR number as a repo name
|
||||||
|
if repo.parse::<u64>().is_ok() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(repo)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn no_repo_error(&self) -> eyre::Error {
|
||||||
|
use PrSubcommand::*;
|
||||||
|
match &self.command {
|
||||||
|
Search { .. } | Create { .. } => {
|
||||||
|
eyre::eyre!("can't figure what repo to access, try specifying with `--repo`")
|
||||||
|
}
|
||||||
|
Checkout { .. } => {
|
||||||
|
if git2::Repository::open(".").is_ok() {
|
||||||
|
eyre::eyre!("can't figure out what repo to access, try setting a remote tracking branch")
|
||||||
|
} else {
|
||||||
|
eyre::eyre!("pr checkout only works if the current directory is a git repo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
View { id: pr, .. }
|
||||||
|
| Comment { pr, .. }
|
||||||
|
| Edit { pr, .. }
|
||||||
|
| Close { pr, .. }
|
||||||
|
| Merge { pr, .. } => eyre::eyre!(
|
||||||
|
"can't figure out what repo to access, try specifying with `{{owner}}/{{repo}}#{}`",
|
||||||
|
pr.number
|
||||||
|
),
|
||||||
|
Browse { id } => {
|
||||||
|
let number = id.as_ref().and_then(|s| {
|
||||||
|
let num_s = s.rsplit_once("#").map(|(_, b)| b).unwrap_or(s);
|
||||||
|
num_s.parse::<u64>().ok()
|
||||||
|
});
|
||||||
|
if let Some(number) = number {
|
||||||
|
eyre::eyre!("can't figure out what repo to access, try specifying with `{{owner}}/{{repo}}#{}`", number)
|
||||||
|
} else {
|
||||||
|
eyre::eyre!("can't figure out what repo to access, try specifying with `{{owner}}/{{repo}}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn view_pr(repo: &RepoName, api: &Forgejo, id: u64) -> eyre::Result<()> {
|
pub async fn view_pr(repo: &RepoName, api: &Forgejo, id: u64) -> eyre::Result<()> {
|
||||||
|
@ -670,18 +745,8 @@ async fn checkout_pr(
|
||||||
repo: &RepoName,
|
repo: &RepoName,
|
||||||
api: &Forgejo,
|
api: &Forgejo,
|
||||||
pr: PrNumber,
|
pr: PrNumber,
|
||||||
repo_specified: bool,
|
|
||||||
branch_name: Option<String>,
|
branch_name: Option<String>,
|
||||||
) -> eyre::Result<()> {
|
) -> eyre::Result<()> {
|
||||||
// this is so you don't checkout a pull request from an entirely different
|
|
||||||
// repository. i.e. in this repo I could run
|
|
||||||
// `fj pr -r codeberg.org/forgejo/forgejo checkout [num]` and have forgejo
|
|
||||||
// appear in this repo.
|
|
||||||
eyre::ensure!(
|
|
||||||
!repo_specified,
|
|
||||||
"Cannot checkout PR, `--repo` is not allowed when checking out a pull request"
|
|
||||||
);
|
|
||||||
|
|
||||||
let local_repo = git2::Repository::open(".").unwrap();
|
let local_repo = git2::Repository::open(".").unwrap();
|
||||||
|
|
||||||
let mut options = git2::StatusOptions::new();
|
let mut options = git2::StatusOptions::new();
|
||||||
|
|
Loading…
Reference in a new issue