Skip to content

Commit

Permalink
fix(submit): prevent submitting open prs (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
refcell authored Oct 24, 2024
1 parent 879f04d commit 2b0a59c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
38 changes: 38 additions & 0 deletions src/ctx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use crate::{
config::StConfig,
constants::{GIT_DIR, ST_CTX_FILE_NAME},
errors::{StError, StResult},
git::RepositoryExt,
tree::StackTree,
};
use git2::{BranchType, Repository};
use octocrab::Octocrab;
use std::path::PathBuf;

mod actions;
Expand Down Expand Up @@ -47,6 +49,42 @@ impl<'a> StContext<'a> {
}
}

/// Returns if the current branch has an open PR.
/// Returns the branch name and it's parent branch name.
pub async fn get_open_pr(&self, client: &Octocrab) -> StResult<Option<(String, String)>> {
let (owner, repo) = self.owner_and_repository()?;
let page = client
.pulls(&owner, &repo)
.list()
.state(octocrab::params::State::Open)
.sort(octocrab::params::pulls::Sort::Popularity)
.direction(octocrab::params::Direction::Ascending)
.per_page(255)
.send()
.await?;
let mut found = false;
let current_branch = self.repository.current_branch_name()?;
for item in page.items.iter() {
if item.head.ref_field == current_branch {
found = true;
break;
}
}
if found {
let current_tracked_branch = self
.tree
.get(&current_branch)
.ok_or_else(|| StError::BranchNotTracked(current_branch.to_string()))?;
let upstack = current_tracked_branch.parent.as_ref();
return Ok(Some((
current_branch,
upstack.map(|s| s.as_ref()).unwrap_or("unknown").to_string(),
)));
}

Ok(None)
}

/// Loads the [StackTree] for the given [Repository], and assembles a [StContext].
pub fn try_load(cfg: StConfig, repository: &'a Repository) -> StResult<Option<Self>> {
let store_path = ctx_path(repository).ok_or(StError::GitRepositoryRootNotFound)?;
Expand Down
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ pub enum StError {
/// A remote pull request could not be found.
#[error("Remote pull request not found.")]
PullRequestNotFound,
/// A pull request is already open.
#[error("Pull request is already open for branch {} with parent `{}`.", Color::Blue.paint(.0), Color::Blue.paint(.1))]
PullRequestAlreadyOpen(String, String),

// ---- [ Git Errors ] ----
/// `st` mused be run within a git repository.
Expand Down
9 changes: 8 additions & 1 deletion src/subcommands/remote/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ impl SubmitCmd {

// Perform pre-flight checks.
println!("🔍 Checking for closed pull requests...");
self.pre_flight(&mut ctx, &stack, &mut pulls).await?;
self.pre_flight(&gh_client, &mut ctx, &stack, &mut pulls)
.await?;

// Submit the stack.
println!(
Expand All @@ -56,13 +57,19 @@ impl SubmitCmd {
/// Performs pre-flight checks before submitting the stack.
async fn pre_flight(
&self,
gh_client: &Octocrab,
ctx: &mut StContext<'_>,
stack: &[String],
pulls: &mut PullRequestHandler<'_>,
) -> StResult<()> {
// Return early if the stack is not restacked or the current working tree is dirty.
ctx.check_cleanliness(stack)?;

// Check if the current branch has an open PR.
if let Some((c, p)) = ctx.get_open_pr(gh_client).await? {
return Err(StError::PullRequestAlreadyOpen(c, p));
}

// Check if any PRs have been closed, and offer to delete them before starting the submission process.
let num_closed = ctx
.delete_closed_branches(
Expand Down

0 comments on commit 2b0a59c

Please sign in to comment.