cli: Fix patch open/update when out-of-sync

Trying to open or update Patch will fail if the user's working copy is
out of sync with the Radicle projects canonical head.

Fix this by always operating on the storage when opening or
updating a patch.
This commit is contained in:
Slack Coder 2023-04-24 10:54:14 -05:00 committed by Alexis Sellier
parent e757750398
commit 2667569a6d
No known key found for this signature in database
3 changed files with 21 additions and 22 deletions

View File

@ -35,8 +35,8 @@ fn get_branch(git_ref: git::Qualified) -> git::RefString {
std::iter::once(head).chain(tail).collect() std::iter::once(head).chain(tail).collect()
} }
/// Determine the merge target for this patch. This can ben any tracked remote's "default" /// Determine the merge target for this patch. This can be any tracked remote's "default" branch,
/// branch, as well as your own (eg. `rad/master`). /// as well as your own (eg. `rad/master`).
pub fn get_merge_target( pub fn get_merge_target(
storage: &Repository, storage: &Repository,
head_branch: &git::raw::Branch, head_branch: &git::raw::Branch,
@ -170,7 +170,7 @@ pub fn find_unmerged_with_base(
target_head: Oid, target_head: Oid,
merge_base: Oid, merge_base: Oid,
patches: &Patches, patches: &Patches,
workdir: &git::raw::Repository, storage: &Repository,
whoami: &Did, whoami: &Did,
) -> anyhow::Result<Vec<(PatchId, Patch, Clock)>> { ) -> anyhow::Result<Vec<(PatchId, Patch, Clock)>> {
// My patches. // My patches.
@ -187,7 +187,7 @@ pub fn find_unmerged_with_base(
continue; continue;
} }
// Merge-base between the two patches. // Merge-base between the two patches.
if workdir.merge_base(**patch.head(), target_head)? == merge_base { if storage.backend.merge_base(**patch.head(), target_head)? == merge_base {
matches.push((id, patch, clock)); matches.push((id, patch, clock));
} }
} }

View File

@ -26,11 +26,11 @@ and description.
pub fn handle_patch_message( pub fn handle_patch_message(
message: term::patch::Message, message: term::patch::Message,
workdir: &git::raw::Repository, storage: &Repository,
head_branch: &git::raw::Branch, head_branch: &git::raw::Branch,
) -> anyhow::Result<(String, String)> { ) -> anyhow::Result<(String, String)> {
let head_oid = branch_oid(head_branch)?; let head_oid = branch_oid(head_branch)?;
let head_commit = workdir.find_commit(*head_oid)?; let head_commit = storage.backend.find_commit(*head_oid)?;
let commit_message = head_commit let commit_message = head_commit
.message() .message()
.ok_or(anyhow!("commit summary is not valid UTF-8; aborting"))?; .ok_or(anyhow!("commit summary is not valid UTF-8; aborting"))?;
@ -47,7 +47,7 @@ pub fn handle_patch_message(
} }
fn show_patch_commit_info( fn show_patch_commit_info(
workdir: &git::raw::Repository, storage: &Repository,
node_id: &NodeId, node_id: &NodeId,
head_branch: &git::raw::Branch, head_branch: &git::raw::Branch,
target_ref: &git::RefStr, target_ref: &git::RefStr,
@ -55,8 +55,8 @@ fn show_patch_commit_info(
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let head_oid = branch_oid(head_branch)?; let head_oid = branch_oid(head_branch)?;
// The merge base is basically the commit at which the histories diverge. // The merge base is basically the commit at which the histories diverge.
let base_oid = workdir.merge_base(*target_oid, *head_oid)?; let base_oid = storage.backend.merge_base(*target_oid, *head_oid)?;
let commits = patch_commits(workdir, &base_oid, &head_oid)?; let commits = patch_commits(&storage.backend, &base_oid, &head_oid)?;
term::info!( term::info!(
"{} <- {}/{} ({})", "{} <- {}/{} ({})",
@ -69,7 +69,7 @@ fn show_patch_commit_info(
// TODO: Test case where the target branch has been re-written passed the merge-base, since the fork was created // TODO: Test case where the target branch has been re-written passed the merge-base, since the fork was created
// This can also happen *after* the patch is created. // This can also happen *after* the patch is created.
term::patch::print_commits_ahead_behind(workdir, *head_oid, *target_oid)?; term::patch::print_commits_ahead_behind(&storage.backend, *head_oid, *target_oid)?;
// List commits in patch that aren't in the target branch. // List commits in patch that aren't in the target branch.
term::blank(); term::blank();
@ -91,7 +91,6 @@ pub fn run(
let mut patches = patch::Patches::open(storage)?; let mut patches = patch::Patches::open(storage)?;
let head_branch = try_branch(workdir.head()?)?; let head_branch = try_branch(workdir.head()?)?;
let head_branch_name = push_to_storage(workdir, storage, &head_branch, &options)?; let head_branch_name = push_to_storage(workdir, storage, &head_branch, &options)?;
let (target_ref, target_oid) = get_merge_target(storage, &head_branch)?; let (target_ref, target_oid) = get_merge_target(storage, &head_branch)?;
if head_branch.upstream().is_err() { if head_branch.upstream().is_err() {
@ -109,15 +108,15 @@ pub fn run(
// base. // base.
if !quiet { if !quiet {
show_patch_commit_info(workdir, profile.id(), &head_branch, &target_ref, target_oid)?; show_patch_commit_info(storage, profile.id(), &head_branch, &target_ref, target_oid)?;
term::blank(); term::blank();
} }
// TODO: List matching working copy refs for all targets. // TODO: List matching working copy refs for all targets.
let (title, description) = handle_patch_message(message, workdir, &head_branch)?; let (title, description) = handle_patch_message(message, storage, &head_branch)?;
let head_oid = branch_oid(&head_branch)?; let head_oid = branch_oid(&head_branch)?;
let base_oid = workdir.merge_base(*target_oid, *head_oid)?; let base_oid = storage.backend.merge_base(*target_oid, *head_oid)?;
let signer = term::signer(profile)?; let signer = term::signer(profile)?;
let patch = if draft { let patch = if draft {
patches.draft( patches.draft(

View File

@ -16,16 +16,16 @@ blank is also okay.
fn select_patch( fn select_patch(
patches: &patch::Patches, patches: &patch::Patches,
workdir: &git::raw::Repository, storage: &Repository,
head_branch: &git::raw::Branch, head_branch: &git::raw::Branch,
target_oid: git::Oid, target_oid: git::Oid,
whoami: &Did, whoami: &Did,
) -> anyhow::Result<patch::PatchId> { ) -> anyhow::Result<patch::PatchId> {
let head_oid = branch_oid(head_branch)?; let head_oid = branch_oid(head_branch)?;
let base_oid = workdir.merge_base(*target_oid, *head_oid)?; let base_oid = storage.backend.merge_base(*target_oid, *head_oid)?;
let mut result = let mut result =
find_unmerged_with_base(*head_oid, *target_oid, base_oid, patches, workdir, whoami)?; find_unmerged_with_base(*head_oid, *target_oid, base_oid, patches, storage, whoami)?;
let Some((id, _, _)) = result.pop() else { let Some((id, _, _)) = result.pop() else {
anyhow::bail!("No patches found to update, please specify a patch id"); anyhow::bail!("No patches found to update, please specify a patch id");
@ -40,7 +40,7 @@ fn select_patch(
} }
fn show_update_commit_info( fn show_update_commit_info(
workdir: &git::raw::Repository, storage: &Repository,
current_revision: &patch::Revision, current_revision: &patch::Revision,
head_branch: &git::raw::Branch, head_branch: &git::raw::Branch,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
@ -54,7 +54,7 @@ fn show_update_commit_info(
// Difference between the two revisions. // Difference between the two revisions.
let head_oid = branch_oid(head_branch)?; let head_oid = branch_oid(head_branch)?;
term::patch::print_commits_ahead_behind(workdir, *head_oid, *current_revision.head())?; term::patch::print_commits_ahead_behind(&storage.backend, *head_oid, *current_revision.head())?;
Ok(()) Ok(())
} }
@ -79,7 +79,7 @@ pub fn run(
let patch_id = match patch_id { let patch_id = match patch_id {
Some(patch_id) => patch_id, Some(patch_id) => patch_id,
None => select_patch(&patches, workdir, &head_branch, target_oid, &profile.did())?, None => select_patch(&patches, storage, &head_branch, target_oid, &profile.did())?,
}; };
let Ok(mut patch) = patches.get_mut(&patch_id) else { let Ok(mut patch) = patches.get_mut(&patch_id) else {
anyhow::bail!("Patch `{patch_id}` not found"); anyhow::bail!("Patch `{patch_id}` not found");
@ -95,11 +95,11 @@ pub fn run(
} }
if !quiet { if !quiet {
show_update_commit_info(workdir, current_revision, &head_branch)?; show_update_commit_info(storage, current_revision, &head_branch)?;
} }
let head_oid = branch_oid(&head_branch)?; let head_oid = branch_oid(&head_branch)?;
let base_oid = workdir.merge_base(*target_oid, *head_oid)?; let base_oid = storage.backend.merge_base(*target_oid, *head_oid)?;
let message = message.get(REVISION_MSG)?; let message = message.get(REVISION_MSG)?;
let message = message.replace(REVISION_MSG.trim(), ""); let message = message.replace(REVISION_MSG.trim(), "");
let message = message.trim(); let message = message.trim();