upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/lib/git
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-02-18 21:17:41 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-18 21:17:41 +0000
commit09db17fd719ddd42c5afad24e1a8e71735374f8e (patch)
tree65d0d4d02c3c43cac9f5b1a8d62697aae4864424 /src/lib/git
parent73d829b916d87626f33ea2adead0c48f1d9d737d (diff)
fix: thread applied OID through patch chain correctly
When applying a chain of patches without parent-commit tags, each patch's parent was resolved independently, meaning patch2 would not parent off the OID patch1 actually produced. Thread next_parent_override through the loop and guard the early-return in create_commit_from_patch so the override is always honoured.
Diffstat (limited to 'src/lib/git')
-rw-r--r--src/lib/git/mod.rs35
1 files changed, 21 insertions, 14 deletions
diff --git a/src/lib/git/mod.rs b/src/lib/git/mod.rs
index 9f86b5f..dc84ee3 100644
--- a/src/lib/git/mod.rs
+++ b/src/lib/git/mod.rs
@@ -619,26 +619,31 @@ impl RepoActions for Repo {
619 // apply commits 619 // apply commits
620 patches_to_apply.reverse(); 620 patches_to_apply.reverse();
621 621
622 // When optional tags are absent, the reconstructed OID of each applied patch
623 // may differ from its tagged commit id (e.g. GPG-signed commits, different
624 // tooling). We therefore thread the actual applied OID forward as the
625 // parent override for the next patch, so the chain builds correctly
626 // even when parent-commit tags are absent or point to a
627 // pre-reconstruction OID.
628 let mut next_parent_override: Option<String> = None;
629
622 for patch in &patches_to_apply { 630 for patch in &patches_to_apply {
623 // The commit id from the tag (or mbox envelope) is the authoritative id
624 // when the optional `commit` nostr tag is present. When it is absent the
625 // mbox envelope SHA1 is used as a best-effort value — it will often differ
626 // from the reconstructed commit's actual OID (e.g. GPG-signed commits).
627 // We therefore always use the OID returned by create_commit_from_patch as
628 // the branch tip, falling back to the tag commit id only when the commit
629 // already exists in the repo (meaning it was previously applied correctly).
630 let tag_commit_id = get_commit_id_from_patch(patch).ok(); 631 let tag_commit_id = get_commit_id_from_patch(patch).ok();
631 let applied_oid = if let Some(ref id) = tag_commit_id { 632 let applied_oid = if let Some(ref id) = tag_commit_id {
632 if self.does_commit_exist(id)? { 633 if self.does_commit_exist(id)? && next_parent_override.is_none() {
633 // Commit already exists (e.g. previously fetched), use it directly. 634 // Commit already exists and we have no override from a prior
635 // reconstruction — use the existing commit directly.
634 id.clone() 636 id.clone()
635 } else { 637 } else {
636 self.create_commit_from_patch(patch, None)?.to_string() 638 self.create_commit_from_patch(patch, next_parent_override.take())?
639 .to_string()
637 } 640 }
638 } else { 641 } else {
639 // No commit id available at all — apply and use the resulting OID. 642 // No commit id available at all — apply and use the resulting OID.
640 self.create_commit_from_patch(patch, None)?.to_string() 643 self.create_commit_from_patch(patch, next_parent_override.take())?
644 .to_string()
641 }; 645 };
646 next_parent_override = Some(applied_oid.clone());
642 self.create_branch_at_commit(branch_name, &applied_oid)?; 647 self.create_branch_at_commit(branch_name, &applied_oid)?;
643 self.checkout(branch_name)?; 648 self.checkout(branch_name)?;
644 } 649 }
@@ -650,9 +655,11 @@ impl RepoActions for Repo {
650 parent_commit_id_override: Option<String>, 655 parent_commit_id_override: Option<String>,
651 ) -> Result<Oid> { 656 ) -> Result<Oid> {
652 let commit_id = get_commit_id_from_patch(patch); 657 let commit_id = get_commit_id_from_patch(patch);
653 if let Ok(commit_id) = &commit_id { 658 if parent_commit_id_override.is_none() {
654 if self.does_commit_exist(commit_id).unwrap_or(false) { 659 if let Ok(commit_id) = &commit_id {
655 return Ok(Oid::from_str(commit_id)?); 660 if self.does_commit_exist(commit_id).unwrap_or(false) {
661 return Ok(Oid::from_str(commit_id)?);
662 }
656 } 663 }
657 } 664 }
658 665