diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-18 21:17:41 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-18 21:17:41 +0000 |
| commit | 09db17fd719ddd42c5afad24e1a8e71735374f8e (patch) | |
| tree | 65d0d4d02c3c43cac9f5b1a8d62697aae4864424 /src/lib/git/mod.rs | |
| parent | 73d829b916d87626f33ea2adead0c48f1d9d737d (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/mod.rs')
| -rw-r--r-- | src/lib/git/mod.rs | 35 |
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 | ||