Skip to content

Commit 116be0d

Browse files
committed
Move diff loading to a thread
1 parent 934f618 commit 116be0d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2632
-1578
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ redundant_closure_for_method_calls = "allow"
214214
redundant_pub_crate = "allow"
215215
ref_patterns = "allow"
216216
self_named_module_files = "allow"
217+
semicolon_outside_block = "allow"
217218
single_call_fn = "allow"
218219
std_instead_of_alloc = "allow"
219220
std_instead_of_core = "allow"

src/application.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ pub(crate) use crate::application::app_data::AppData;
99
use crate::{
1010
Args,
1111
Exit,
12-
config::{Config, ConfigLoader},
12+
config::{Config, ConfigLoader, DiffIgnoreWhitespaceSetting},
13+
diff::{self, CommitDiffLoader, CommitDiffLoaderOptions},
1314
display::Display,
14-
git::{Repository, open_repository_from_env},
15+
git::open_repository_from_env,
1516
help::build_help,
1617
input::{Event, EventHandler, EventReaderFn, KeyBindings, StandardEvent},
1718
module::{self, ExitStatus, ModuleHandler, State},
@@ -73,20 +74,35 @@ where ModuleProvider: module::ModuleProvider + Send + 'static
7374
let search_state = search_threads.state();
7475
threads.push(Box::new(search_threads));
7576

77+
let commit_diff_loader_options = CommitDiffLoaderOptions::new()
78+
.context_lines(config.git.diff_context)
79+
.copies(config.git.diff_copies)
80+
.ignore_whitespace(config.diff_ignore_whitespace == DiffIgnoreWhitespaceSetting::All)
81+
.ignore_whitespace_change(config.diff_ignore_whitespace == DiffIgnoreWhitespaceSetting::Change)
82+
.ignore_blank_lines(config.diff_ignore_blank_lines)
83+
.interhunk_context(config.git.diff_interhunk_lines)
84+
.renames(config.git.diff_renames, config.git.diff_rename_limit);
85+
let commit_diff_loader = CommitDiffLoader::new(config_loader.eject_repository(), commit_diff_loader_options);
86+
87+
let diff_update_handler = Self::create_diff_update_handler(input_state.clone());
88+
let diff_thread = diff::thread::Thread::new(commit_diff_loader, diff_update_handler);
89+
let diff_state = diff_thread.state();
90+
threads.push(Box::new(diff_thread));
91+
7692
let keybindings = KeyBindings::new(&config.key_bindings);
93+
7794
let app_data = AppData::new(
7895
config,
7996
State::WindowSizeError,
8097
Arc::clone(&todo_file),
98+
diff_state.clone(),
8199
view_state.clone(),
82100
input_state.clone(),
83101
search_state.clone(),
84102
);
85103

86-
let module_handler = ModuleHandler::new(
87-
EventHandler::new(keybindings),
88-
ModuleProvider::new(Repository::from(config_loader.eject_repository()), &app_data),
89-
);
104+
let module_handler = ModuleHandler::new(EventHandler::new(keybindings), ModuleProvider::new(&app_data));
105+
90106
let process = Process::new(&app_data, initial_display_size, module_handler, thread_statuses.clone());
91107
let process_threads = process::Thread::new(process.clone());
92108
threads.push(Box::new(process_threads));
@@ -184,6 +200,10 @@ where ModuleProvider: module::ModuleProvider + Send + 'static
184200
fn create_search_update_handler(input_state: crate::input::State) -> impl Fn() + Send + Sync {
185201
move || input_state.push_event(Event::Standard(StandardEvent::SearchUpdate))
186202
}
203+
204+
fn create_diff_update_handler(input_state: crate::input::State) -> impl Fn() + Send + Sync {
205+
move || input_state.push_event(Event::Standard(StandardEvent::DiffUpdate))
206+
}
187207
}
188208

189209
#[cfg(all(unix, test))]

src/application/app_data.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ use std::sync::Arc;
22

33
use parking_lot::Mutex;
44

5-
use crate::{config::Config, input, module, search, todo_file::TodoFile, view};
5+
use crate::{config::Config, diff, input, module, search, todo_file::TodoFile, view};
66

77
#[derive(Clone, Debug)]
88
pub(crate) struct AppData {
99
config: Arc<Config>,
1010
active_module: Arc<Mutex<module::State>>,
1111
todo_file: Arc<Mutex<TodoFile>>,
12+
diff_state: diff::thread::State,
1213
view_state: view::State,
1314
input_state: input::State,
1415
search_state: search::State,
@@ -19,6 +20,7 @@ impl AppData {
1920
config: Config,
2021
active_module: module::State,
2122
todo_file: Arc<Mutex<TodoFile>>,
23+
diff_state: diff::thread::State,
2224
view_state: view::State,
2325
input_state: input::State,
2426
search_state: search::State,
@@ -27,6 +29,7 @@ impl AppData {
2729
config: Arc::new(config),
2830
active_module: Arc::new(Mutex::new(active_module)),
2931
todo_file,
32+
diff_state,
3033
view_state,
3134
input_state,
3235
search_state,
@@ -45,6 +48,10 @@ impl AppData {
4548
Arc::clone(&self.todo_file)
4649
}
4750

51+
pub(crate) fn diff_state(&self) -> diff::thread::State {
52+
self.diff_state.clone()
53+
}
54+
4855
pub(crate) fn view_state(&self) -> view::State {
4956
self.view_state.clone()
5057
}

src/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl Config {
9797
impl TryFrom<&ConfigLoader> for Config {
9898
type Error = ConfigError;
9999

100-
/// Creates a new Config instance loading the Git Config using [`crate::git::Repository`].
100+
/// Creates a new Config instance loading the Git Config.
101101
///
102102
/// # Errors
103103
///

src/diff.rs

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ mod reference_kind;
1313
mod status;
1414
mod user;
1515

16+
pub(crate) mod thread;
17+
1618
pub(crate) use self::{
1719
commit::Commit,
1820
commit_diff::CommitDiff,

src/diff/commit.rs

+53-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::time::UNIX_EPOCH;
2+
13
use chrono::{DateTime, Local, TimeZone as _};
24

35
use crate::{
@@ -6,7 +8,7 @@ use crate::{
68
};
79

810
/// Represents a commit.
9-
#[derive(Debug, PartialEq, Eq)]
11+
#[derive(Debug, Clone, PartialEq, Eq)]
1012
pub(crate) struct Commit {
1113
pub(crate) hash: String,
1214
pub(crate) reference: Option<Reference>,
@@ -19,6 +21,20 @@ pub(crate) struct Commit {
1921
}
2022

2123
impl Commit {
24+
#[must_use]
25+
pub(crate) fn empty() -> Self {
26+
Self {
27+
hash: String::from("0000000000000000000000000000000000000000"),
28+
reference: None,
29+
author: User::new(None, None),
30+
authored_date: None,
31+
message: None,
32+
committer: None,
33+
committed_date: DateTime::from(UNIX_EPOCH),
34+
summary: None,
35+
}
36+
}
37+
2238
/// Get the hash of the commit
2339
#[must_use]
2440
pub(crate) fn hash(&self) -> &str {
@@ -131,6 +147,34 @@ mod tests {
131147
with_temp_repository,
132148
};
133149

150+
impl Commit {
151+
pub(crate) fn new_with_hash(hash: &str) -> Self {
152+
Self {
153+
hash: String::from(hash),
154+
reference: None,
155+
author: User::new(None, None),
156+
authored_date: None,
157+
message: None,
158+
committer: None,
159+
committed_date: DateTime::from(UNIX_EPOCH),
160+
summary: None,
161+
}
162+
}
163+
}
164+
165+
#[test]
166+
fn empty() {
167+
let commit = Commit::empty();
168+
assert_eq!(commit.hash(), "0000000000000000000000000000000000000000");
169+
assert_none!(commit.reference());
170+
assert_eq!(commit.author(), &User::new(None, None));
171+
assert_none!(commit.authored_date());
172+
assert_none!(commit.message());
173+
assert_none!(commit.committer());
174+
assert_eq!(commit.committed_date().timestamp(), 0);
175+
assert_none!(commit.summary());
176+
}
177+
134178
#[test]
135179
fn hash() {
136180
let commit = CommitBuilder::new("0123456789ABCDEF").build();
@@ -180,26 +224,25 @@ mod tests {
180224
#[test]
181225
fn new_authored_date_same_committed_date() {
182226
with_temp_repository(|repository| {
183-
let repo = crate::git::Repository::from(repository);
184-
create_commit(&repo, Some(CreateCommitOptions::new().author_time(JAN_2021_EPOCH)));
185-
let commit = repo.find_commit("refs/heads/main").unwrap();
227+
let commit = create_commit(
228+
&repository,
229+
Some(CreateCommitOptions::new().author_time(JAN_2021_EPOCH)),
230+
);
186231
assert_none!(commit.authored_date());
187232
});
188233
}
189234

190235
#[test]
191236
fn new_authored_date_different_than_committed() {
192237
with_temp_repository(|repository| {
193-
let repo = crate::git::Repository::from(repository);
194-
create_commit(
195-
&repo,
238+
let commit = create_commit(
239+
&repository,
196240
Some(
197241
CreateCommitOptions::new()
198242
.commit_time(JAN_2021_EPOCH)
199243
.author_time(JAN_2021_EPOCH + 1),
200244
),
201245
);
202-
let commit = repo.find_commit("refs/heads/main").unwrap();
203246
assert_some_eq!(
204247
commit.authored_date(),
205248
&DateTime::parse_from_rfc3339("2021-01-01T00:00:01Z").unwrap()
@@ -210,9 +253,7 @@ mod tests {
210253
#[test]
211254
fn new_committer_different_than_author() {
212255
with_temp_repository(|repository| {
213-
let repo = crate::git::Repository::from(repository);
214-
create_commit(&repo, Some(CreateCommitOptions::new().committer("Committer")));
215-
let commit = repo.find_commit("refs/heads/main").unwrap();
256+
let commit = create_commit(&repository, Some(CreateCommitOptions::new().committer("Committer")));
216257
assert_some_eq!(
217258
commit.committer(),
218259
&User::new(Some("Committer"), Some("[email protected]"))
@@ -223,8 +264,7 @@ mod tests {
223264
#[test]
224265
fn new_committer_same_as_author() {
225266
with_temp_repository(|repository| {
226-
let repo = crate::git::Repository::from(repository);
227-
let commit = repo.find_commit("refs/heads/main").unwrap();
267+
let commit = create_commit(&repository, None);
228268
assert_none!(commit.committer());
229269
});
230270
}

0 commit comments

Comments
 (0)