mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-02 10:10:28 +08:00
Fix patch diff for merge-commit revisions
`list_commits` walked back from the revision head and stopped at the first commit equal to `base`. A merge commit reaches `base` through one of its parents, so the walk truncated there and dropped everything the other parent contributed: a revision whose head merges the target branch in looked like a single-commit revision.
This commit is contained in:
@@ -781,18 +781,20 @@ pub trait Repo: Profile {
|
||||
let profile = self.profile();
|
||||
let repo = profile.storage.repository(rid)?;
|
||||
|
||||
let repo = surf::Repository::open(repo.path())?;
|
||||
let history = repo.history(&head)?;
|
||||
// Hide `base` from the walk rather than stopping at the first commit
|
||||
// that equals it. A merge commit reaches `base` through one of its
|
||||
// parents, so truncating there drops every commit the other parent
|
||||
// contributes and leaves the revision looking like a single commit.
|
||||
let mut walk = repo.backend.revwalk()?;
|
||||
walk.set_sorting(git2::Sort::TOPOLOGICAL | git2::Sort::TIME)?;
|
||||
walk.push(git::raw::Oid::from_str(&head)?)?;
|
||||
walk.hide(git::raw::Oid::from_str(&base)?)?;
|
||||
|
||||
let commits = history
|
||||
.take_while(|c| {
|
||||
if let Ok(c) = c {
|
||||
c.id.to_string() != base
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.filter_map(|c| c.map(Into::into).ok())
|
||||
let surf_repo = surf::Repository::open(repo.path())?;
|
||||
let commits = walk
|
||||
.filter_map(|oid| oid.ok())
|
||||
.filter_map(|oid| surf_repo.commit(git::Oid::from(oid)).ok())
|
||||
.map(Into::into)
|
||||
.collect();
|
||||
|
||||
Ok(commits)
|
||||
|
||||
@@ -345,13 +345,16 @@
|
||||
});
|
||||
|
||||
// A single-commit revision has nothing to choose between, so select that
|
||||
// commit automatically to surface its message.
|
||||
// commit automatically to surface its message. The diff stays the
|
||||
// revision's own range: a merge commit's first parent is the side it merged
|
||||
// into, not the revision base, so narrowing to the commit diff there would
|
||||
// show the other branch's changes instead of the patch's.
|
||||
$effect(() => {
|
||||
if (commitList.length === 1 && !selectedCommit) {
|
||||
const only = commitList[0];
|
||||
selectRevision({
|
||||
headId: only.id,
|
||||
baseId: only.parents[0],
|
||||
headId: revision.head,
|
||||
baseId: revision.base,
|
||||
commitId: only.id,
|
||||
commit: only,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user