Skip to content

Commit 7335cd1

Browse files
authored
fix sorting of commits in diff view (#1747)
1 parent 1fa6f9b commit 7335cd1

File tree

8 files changed

+106
-62
lines changed

8 files changed

+106
-62
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7777
* fix expansion of `~` in `commit.template` ([#1745](https://github.com/extrawurst/gitui/pull/1745))
7878
* fix hunk (un)staging/reset for # of context lines != 3 ([#1746](https://github.com/extrawurst/gitui/issues/1746))
7979
* fix delay when opening external editor ([#1506](https://github.com/extrawurst/gitui/issues/1506))
80+
* fix ordering of commits in diff view [[@Joshix-1](https://github.com/Joshix-1)]([#1747](https://github.com/extrawurst/gitui/issues/1747))
8081

8182
### Changed
8283
* Copy full Commit Hash by default [[@AmmarAbouZor](https://github.com/AmmarAbouZor)] ([#1836](https://github.com/extrawurst/gitui/issues/1836))

Diff for: asyncgit/src/commit_files.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
error::Result,
3-
sync::{self, CommitId, RepoPath},
3+
sync::{self, commit_files::OldNew, CommitId, RepoPath},
44
AsyncGitNotification, StatusItem,
55
};
66
use crossbeam_channel::Sender;
@@ -36,6 +36,15 @@ impl From<(CommitId, CommitId)> for CommitFilesParams {
3636
}
3737
}
3838

39+
impl From<OldNew<CommitId>> for CommitFilesParams {
40+
fn from(old_new: OldNew<CommitId>) -> Self {
41+
Self {
42+
id: old_new.new,
43+
other: Some(old_new.old),
44+
}
45+
}
46+
}
47+
3948
///
4049
pub struct AsyncCommitFiles {
4150
current:

Diff for: asyncgit/src/diff.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use crate::{
22
error::Result,
33
hash,
4-
sync::{self, diff::DiffOptions, CommitId, RepoPath},
4+
sync::{
5+
self, commit_files::OldNew, diff::DiffOptions, CommitId,
6+
RepoPath,
7+
},
58
AsyncGitNotification, FileDiff,
69
};
710
use crossbeam_channel::Sender;
@@ -17,7 +20,7 @@ use std::{
1720
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
1821
pub enum DiffType {
1922
/// diff two commits
20-
Commits((CommitId, CommitId)),
23+
Commits(OldNew<CommitId>),
2124
/// diff in a given commit
2225
Commit(CommitId),
2326
/// diff against staged file

Diff for: asyncgit/src/sync/commit_files.rs

+48-19
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,37 @@ use crate::{
88
};
99
use git2::{Diff, Repository};
1010
use scopetime::scope_time;
11-
use std::{cmp::Ordering, collections::HashSet};
11+
use std::collections::HashSet;
12+
13+
/// struct containing a new and an old version
14+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
15+
pub struct OldNew<T> {
16+
/// The old version
17+
pub old: T,
18+
/// The new version
19+
pub new: T,
20+
}
21+
22+
/// Sort two commits.
23+
pub fn sort_commits(
24+
repo: &Repository,
25+
commits: (CommitId, CommitId),
26+
) -> Result<OldNew<CommitId>> {
27+
if repo.graph_descendant_of(
28+
commits.0.get_oid(),
29+
commits.1.get_oid(),
30+
)? {
31+
Ok(OldNew {
32+
old: commits.1,
33+
new: commits.0,
34+
})
35+
} else {
36+
Ok(OldNew {
37+
old: commits.0,
38+
new: commits.1,
39+
})
40+
}
41+
}
1242

1343
/// get all files that are part of a commit
1444
pub fn get_commit_files(
@@ -21,7 +51,12 @@ pub fn get_commit_files(
2151
let repo = repo(repo_path)?;
2252

2353
let diff = if let Some(other) = other {
24-
get_compare_commits_diff(&repo, (id, other), None, None)?
54+
get_compare_commits_diff(
55+
&repo,
56+
sort_commits(&repo, (id, other))?,
57+
None,
58+
None,
59+
)?
2560
} else {
2661
get_commit_diff(
2762
&repo,
@@ -55,26 +90,20 @@ pub fn get_commit_files(
5590
#[allow(clippy::needless_pass_by_value)]
5691
pub fn get_compare_commits_diff(
5792
repo: &Repository,
58-
ids: (CommitId, CommitId),
93+
ids: OldNew<CommitId>,
5994
pathspec: Option<String>,
6095
options: Option<DiffOptions>,
6196
) -> Result<Diff<'_>> {
6297
// scope_time!("get_compare_commits_diff");
63-
64-
let commits = (
65-
repo.find_commit(ids.0.into())?,
66-
repo.find_commit(ids.1.into())?,
67-
);
68-
69-
let commits = if commits.0.time().cmp(&commits.1.time())
70-
== Ordering::Greater
71-
{
72-
(commits.1, commits.0)
73-
} else {
74-
commits
98+
let commits = OldNew {
99+
old: repo.find_commit(ids.old.into())?,
100+
new: repo.find_commit(ids.new.into())?,
75101
};
76102

77-
let trees = (commits.0.tree()?, commits.1.tree()?);
103+
let trees = OldNew {
104+
old: commits.old.tree()?,
105+
new: commits.new.tree()?,
106+
};
78107

79108
let mut opts = git2::DiffOptions::new();
80109
if let Some(options) = options {
@@ -86,9 +115,9 @@ pub fn get_compare_commits_diff(
86115
opts.pathspec(p.clone());
87116
}
88117

89-
let diff = repo.diff_tree_to_tree(
90-
Some(&trees.0),
91-
Some(&trees.1),
118+
let diff: Diff<'_> = repo.diff_tree_to_tree(
119+
Some(&trees.old),
120+
Some(&trees.new),
92121
Some(&mut opts),
93122
)?;
94123

Diff for: asyncgit/src/sync/diff.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! sync git api for fetching a diff
22
33
use super::{
4-
commit_files::{get_commit_diff, get_compare_commits_diff},
4+
commit_files::{
5+
get_commit_diff, get_compare_commits_diff, OldNew,
6+
},
57
utils::{get_head_repo, work_dir},
68
CommitId, RepoPath,
79
};
@@ -240,20 +242,16 @@ pub fn get_diff_commit(
240242
/// get file changes of a diff between two commits
241243
pub fn get_diff_commits(
242244
repo_path: &RepoPath,
243-
ids: (CommitId, CommitId),
245+
ids: OldNew<CommitId>,
244246
p: String,
245247
options: Option<DiffOptions>,
246248
) -> Result<FileDiff> {
247249
scope_time!("get_diff_commits");
248250

249251
let repo = repo(repo_path)?;
250252
let work_dir = work_dir(&repo)?;
251-
let diff = get_compare_commits_diff(
252-
&repo,
253-
(ids.0, ids.1),
254-
Some(p),
255-
options,
256-
)?;
253+
let diff =
254+
get_compare_commits_diff(&repo, ids, Some(p), options)?;
257255

258256
raw_diff_to_file_diff(&diff, work_dir)
259257
}

Diff for: src/components/commit_details/compare_details.rs

+21-23
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use crate::{
1313
ui::style::SharedTheme,
1414
};
1515
use anyhow::Result;
16-
use asyncgit::sync::{self, CommitDetails, CommitId, RepoPathRef};
16+
use asyncgit::sync::{
17+
self, commit_files::OldNew, CommitDetails, CommitId, RepoPathRef,
18+
};
1719
use crossterm::event::Event;
1820
use ratatui::{
1921
backend::Backend,
@@ -24,7 +26,7 @@ use ratatui::{
2426

2527
pub struct CompareDetailsComponent {
2628
repo: RepoPathRef,
27-
data: Option<(CommitDetails, CommitDetails)>,
29+
data: Option<OldNew<CommitDetails>>,
2830
theme: SharedTheme,
2931
focused: bool,
3032
}
@@ -40,24 +42,20 @@ impl CompareDetailsComponent {
4042
}
4143
}
4244

43-
pub fn set_commits(&mut self, ids: Option<(CommitId, CommitId)>) {
45+
pub fn set_commits(&mut self, ids: Option<OldNew<CommitId>>) {
4446
self.data = ids.and_then(|ids| {
45-
let c1 =
46-
sync::get_commit_details(&self.repo.borrow(), ids.0)
47-
.ok();
48-
let c2 =
49-
sync::get_commit_details(&self.repo.borrow(), ids.1)
50-
.ok();
51-
52-
c1.and_then(|c1| {
53-
c2.map(|c2| {
54-
if c1.author.time < c2.author.time {
55-
(c1, c2)
56-
} else {
57-
(c2, c1)
58-
}
59-
})
60-
})
47+
let old = sync::get_commit_details(
48+
&self.repo.borrow(),
49+
ids.old,
50+
)
51+
.ok()?;
52+
let new = sync::get_commit_details(
53+
&self.repo.borrow(),
54+
ids.new,
55+
)
56+
.ok()?;
57+
58+
Some(OldNew { old, new })
6159
});
6260
}
6361

@@ -122,9 +120,9 @@ impl DrawableComponent for CompareDetailsComponent {
122120
dialog_paragraph(
123121
&strings::commit::compare_details_info_title(
124122
true,
125-
data.0.short_hash(),
123+
data.old.short_hash(),
126124
),
127-
Text::from(self.get_commit_text(&data.0)),
125+
Text::from(self.get_commit_text(&data.old)),
128126
&self.theme,
129127
false,
130128
),
@@ -135,9 +133,9 @@ impl DrawableComponent for CompareDetailsComponent {
135133
dialog_paragraph(
136134
&strings::commit::compare_details_info_title(
137135
false,
138-
data.1.short_hash(),
136+
data.new.short_hash(),
139137
),
140-
Text::from(self.get_commit_text(&data.1)),
138+
Text::from(self.get_commit_text(&data.new)),
141139
&self.theme,
142140
false,
143141
),

Diff for: src/components/commit_details/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use crate::{
1414
};
1515
use anyhow::Result;
1616
use asyncgit::{
17-
sync::CommitTags, AsyncCommitFiles, CommitFilesParams,
17+
sync::{commit_files::OldNew, CommitTags},
18+
AsyncCommitFiles, CommitFilesParams,
1819
};
1920
use compare_details::CompareDetailsComponent;
2021
use crossterm::event::Event;
@@ -81,8 +82,10 @@ impl CommitDetailsComponent {
8182
self.file_tree.set_commit(Some(id.id));
8283

8384
if let Some(other) = id.other {
84-
self.compare_details
85-
.set_commits(Some((id.id, other)));
85+
self.compare_details.set_commits(Some(OldNew {
86+
new: id.id,
87+
old: other,
88+
}));
8689
} else {
8790
self.single_details
8891
.set_commit(Some(id.id), tags.clone());

Diff for: src/components/compare_commits.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::{
1313
};
1414
use anyhow::Result;
1515
use asyncgit::{
16-
sync::{self, CommitId, RepoPathRef},
16+
sync::{self, commit_files::OldNew, CommitId, RepoPathRef},
1717
AsyncDiff, AsyncGitNotification, CommitFilesParams, DiffParams,
1818
DiffType,
1919
};
@@ -222,16 +222,19 @@ impl CompareCommitsComponent {
222222
Ok(())
223223
}
224224

225-
fn get_ids(&self) -> Option<(CommitId, CommitId)> {
225+
fn get_ids(&self) -> Option<OldNew<CommitId>> {
226226
let other = self
227227
.open_request
228228
.as_ref()
229229
.and_then(|open| open.compare_id);
230230

231-
self.open_request
232-
.as_ref()
233-
.map(|open| open.commit_id)
234-
.zip(other)
231+
let this =
232+
self.open_request.as_ref().map(|open| open.commit_id);
233+
234+
Some(OldNew {
235+
old: other?,
236+
new: this?,
237+
})
235238
}
236239

237240
/// called when any tree component changed selection

0 commit comments

Comments
 (0)