Skip to content

Commit 702415c

Browse files
author
Stephan Dilly
authored
full commit detail popup (#113)
see #80
1 parent fa8070b commit 702415c

18 files changed

+695
-181
lines changed

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

+33-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{utils::repo, CommitId};
22
use crate::{error::Result, StatusItem, StatusItemType};
3-
use git2::DiffDelta;
3+
use git2::{Diff, DiffDelta, DiffOptions, Repository};
44
use scopetime::scope_time;
55

66
/// get all files that are part of a commit
@@ -12,19 +12,7 @@ pub fn get_commit_files(
1212

1313
let repo = repo(repo_path)?;
1414

15-
let commit = repo.find_commit(id.into())?;
16-
let commit_tree = commit.tree()?;
17-
let parent = if commit.parent_count() > 0 {
18-
Some(repo.find_commit(commit.parent_id(0)?)?.tree()?)
19-
} else {
20-
None
21-
};
22-
23-
let diff = repo.diff_tree_to_tree(
24-
parent.as_ref(),
25-
Some(&commit_tree),
26-
None,
27-
)?;
15+
let diff = get_commit_diff(&repo, id, None)?;
2816

2917
let mut res = Vec::new();
3018

@@ -48,6 +36,37 @@ pub fn get_commit_files(
4836
Ok(res)
4937
}
5038

39+
///
40+
pub(crate) fn get_commit_diff(
41+
repo: &Repository,
42+
id: CommitId,
43+
pathspec: Option<String>,
44+
) -> Result<Diff<'_>> {
45+
// scope_time!("get_commit_diff");
46+
47+
let commit = repo.find_commit(id.into())?;
48+
let commit_tree = commit.tree()?;
49+
let parent = if commit.parent_count() > 0 {
50+
Some(repo.find_commit(commit.parent_id(0)?)?.tree()?)
51+
} else {
52+
None
53+
};
54+
55+
let mut opt = pathspec.map(|p| {
56+
let mut opts = DiffOptions::new();
57+
opts.pathspec(p);
58+
opts
59+
});
60+
61+
let diff = repo.diff_tree_to_tree(
62+
parent.as_ref(),
63+
Some(&commit_tree),
64+
opt.as_mut(),
65+
)?;
66+
67+
Ok(diff)
68+
}
69+
5170
#[cfg(test)]
5271
mod tests {
5372
use super::get_commit_files;

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

+30-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! sync git api for fetching a diff
22
3-
use super::utils;
3+
use super::{commit_files::get_commit_diff, utils, CommitId};
44
use crate::{error::Error, error::Result, hash};
55
use git2::{
66
Delta, Diff, DiffDelta, DiffFormat, DiffHunk, DiffOptions, Patch,
@@ -81,6 +81,8 @@ pub(crate) fn get_diff_raw<'a>(
8181
stage: bool,
8282
reverse: bool,
8383
) -> Result<Diff<'a>> {
84+
// scope_time!("get_diff_raw");
85+
8486
let mut opt = DiffOptions::new();
8587
opt.pathspec(p);
8688
opt.reverse(reverse);
@@ -119,7 +121,7 @@ pub(crate) fn get_diff_raw<'a>(
119121
Ok(diff)
120122
}
121123

122-
///
124+
/// returns diff of a specific file either in `stage` or workdir
123125
pub fn get_diff(
124126
repo_path: &str,
125127
p: String,
@@ -131,6 +133,32 @@ pub fn get_diff(
131133
let work_dir = work_dir(&repo);
132134
let diff = get_diff_raw(&repo, &p, stage, false)?;
133135

136+
raw_diff_to_file_diff(&diff, work_dir)
137+
}
138+
139+
/// returns diff of a specific file inside a commit
140+
/// see `get_commit_diff`
141+
pub fn get_diff_commit(
142+
repo_path: &str,
143+
id: CommitId,
144+
p: String,
145+
) -> Result<FileDiff> {
146+
scope_time!("get_diff_commit");
147+
148+
let repo = utils::repo(repo_path)?;
149+
let work_dir = work_dir(&repo);
150+
let diff = get_commit_diff(&repo, id, Some(p))?;
151+
152+
raw_diff_to_file_diff(&diff, work_dir)
153+
}
154+
155+
///
156+
fn raw_diff_to_file_diff<'a>(
157+
diff: &'a Diff,
158+
work_dir: &Path,
159+
) -> Result<FileDiff> {
160+
// scope_time!("raw_diff_to_file_diff");
161+
134162
let mut res: FileDiff = FileDiff::default();
135163
let mut current_lines = Vec::new();
136164
let mut current_hunk: Option<HunkHeader> = None;

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

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub mod utils;
1717
pub use commit_details::{get_commit_details, CommitDetails};
1818
pub use commit_files::get_commit_files;
1919
pub use commits_info::{get_commits_info, CommitId, CommitInfo};
20+
pub use diff::get_diff_commit;
2021
pub use hooks::{hooks_commit_msg, hooks_post_commit, HookResult};
2122
pub use hunks::{stage_hunk, unstage_hunk};
2223
pub use ignore::add_to_ignore;

Diff for: src/app.rs

+31-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use crate::{
33
cmdbar::CommandBar,
44
components::{
55
event_pump, CommandBlocking, CommandInfo, CommitComponent,
6-
Component, DrawableComponent, HelpComponent, MsgComponent,
7-
ResetComponent, StashMsgComponent,
6+
Component, DrawableComponent, HelpComponent,
7+
InspectCommitComponent, MsgComponent, ResetComponent,
8+
StashMsgComponent,
89
},
910
keys,
1011
queue::{Action, InternalEvent, NeedsUpdate, Queue},
@@ -33,6 +34,7 @@ pub struct App {
3334
reset: ResetComponent,
3435
commit: CommitComponent,
3536
stashmsg_popup: StashMsgComponent,
37+
inspect_commit_popup: InspectCommitComponent,
3638
cmdbar: CommandBar,
3739
tab: usize,
3840
revlog: Revlog,
@@ -58,12 +60,15 @@ impl App {
5860
queue.clone(),
5961
&theme,
6062
),
63+
inspect_commit_popup: InspectCommitComponent::new(
64+
&queue, sender, &theme,
65+
),
6166
do_quit: false,
6267
cmdbar: CommandBar::new(&theme),
6368
help: HelpComponent::new(&theme),
6469
msg: MsgComponent::new(&theme),
6570
tab: 0,
66-
revlog: Revlog::new(sender, &theme),
71+
revlog: Revlog::new(&queue, sender, &theme),
6772
status_tab: Status::new(sender, &queue, &theme),
6873
stashing_tab: Stashing::new(sender, &queue, &theme),
6974
stashlist_tab: StashList::new(&queue, &theme),
@@ -159,8 +164,11 @@ impl App {
159164
if flags.contains(NeedsUpdate::ALL) {
160165
self.update()?;
161166
}
167+
//TODO: make this a queue event?
168+
//NOTE: set when any tree component changed selection
162169
if flags.contains(NeedsUpdate::DIFF) {
163170
self.status_tab.update_diff()?;
171+
self.inspect_commit_popup.update_diff()?;
164172
}
165173
if flags.contains(NeedsUpdate::COMMANDS) {
166174
self.update_commands();
@@ -191,6 +199,7 @@ impl App {
191199
self.status_tab.update_git(ev)?;
192200
self.stashing_tab.update_git(ev)?;
193201
self.revlog.update_git(ev)?;
202+
self.inspect_commit_popup.update_git(ev)?;
194203

195204
if let AsyncNotification::Status = ev {
196205
//TODO: is that needed?
@@ -210,6 +219,7 @@ impl App {
210219
self.status_tab.anything_pending()
211220
|| self.revlog.any_work_pending()
212221
|| self.stashing_tab.anything_pending()
222+
|| self.inspect_commit_popup.any_work_pending()
213223
}
214224
}
215225

@@ -222,6 +232,7 @@ impl App {
222232
reset,
223233
commit,
224234
stashmsg_popup,
235+
inspect_commit_popup,
225236
help,
226237
revlog,
227238
status_tab,
@@ -356,6 +367,10 @@ impl App {
356367
self.stashmsg_popup.show()?
357368
}
358369
InternalEvent::TabSwitch => self.set_tab(0)?,
370+
InternalEvent::InspectCommit(id) => {
371+
self.inspect_commit_popup.open(id)?;
372+
flags.insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS)
373+
}
359374
};
360375

361376
Ok(flags)
@@ -407,19 +422,31 @@ impl App {
407422
|| self.help.is_visible()
408423
|| self.reset.is_visible()
409424
|| self.msg.is_visible()
425+
|| self.stashmsg_popup.is_visible()
426+
|| self.inspect_commit_popup.is_visible()
410427
}
411428

412429
fn draw_popups<B: Backend>(
413430
&mut self,
414431
f: &mut Frame<B>,
415432
) -> Result<()> {
416-
let size = f.size();
433+
let size = Layout::default()
434+
.direction(Direction::Vertical)
435+
.constraints(
436+
[
437+
Constraint::Min(1),
438+
Constraint::Length(self.cmdbar.height()),
439+
]
440+
.as_ref(),
441+
)
442+
.split(f.size())[0];
417443

418444
self.commit.draw(f, size)?;
419445
self.stashmsg_popup.draw(f, size)?;
420446
self.reset.draw(f, size)?;
421447
self.help.draw(f, size)?;
422448
self.msg.draw(f, size)?;
449+
self.inspect_commit_popup.draw(f, size)?;
423450

424451
Ok(())
425452
}

Diff for: src/components/changes.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl ChangesComponent {
5353
files: FileTreeComponent::new(
5454
title,
5555
focus,
56-
queue.clone(),
56+
Some(queue.clone()),
5757
theme,
5858
),
5959
is_working_dir,
@@ -75,7 +75,8 @@ impl ChangesComponent {
7575

7676
///
7777
pub fn focus_select(&mut self, focus: bool) {
78-
self.files.focus_select(focus)
78+
self.files.focus(focus);
79+
self.files.show_selection(focus);
7980
}
8081

8182
/// returns true if list is empty

0 commit comments

Comments
 (0)