Skip to content

Commit 7cc19f6

Browse files
author
Stephan Dilly
authored
support options for the way we calculate the status (#849)
1 parent 923323b commit 7cc19f6

24 files changed

+638
-75
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
**options**
11+
12+
![options](assets/options.gif)
13+
1014
**drop multiple stashes**
1115

1216
![drop-multiple-stashes](assets/drop-multiple-stashes.gif)
@@ -16,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1620
![name-validation](assets/branch-validation.gif)
1721

1822
## Added
23+
- new options popup (show untracked files, diff settings) ([#849](https://github.com/extrawurst/gitui/issues/849))
1924
- mark and drop multiple stashes ([#854](https://github.com/extrawurst/gitui/issues/854))
2025
- check branch name validity while typing ([#559](https://github.com/extrawurst/gitui/issues/559))
2126
- support deleting remote branch [[@zcorniere](https://github.com/zcorniere)] ([#622](https://github.com/extrawurst/gitui/issues/622))

assets/options.drawio

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="app.diagrams.net" modified="2021-08-17T21:58:53.216Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" etag="DR-vNI6rA-1d9_EpYLQC" version="14.9.7" type="device"><diagram id="cIq82w5ce00BbVejkL92" name="Page-1">5Zldc6IwFIZ/DZfrEJCvS0Xb7exHZ9bd6WxvdlIIkGlMmBir3V+/iQQVg+12Bqm7eqHwkkB43nMCJ1puPF9fc1gWX1iKiOXY6dpyJ5bjABCG8kcpz5Xi+0El5BynutFOmOHfSIu2Vpc4RYtGQ8EYEbhsigmjFCWioUHO2arZLGOkedUS5sgQZgkkpnqHU1FUaugEO/0jwnlRXxn4UXVkDuvG+k4WBUzZak9yp5Ybc8ZEtTVfx4goeDWXqt/VkaPbgXFExd90KLNx+X10/wl4v+6/5fx28jMVH/RZniBZ6hvWgxXPNQHOljRF6iS25Y5XBRZoVsJEHV1Jz6VWiDmRe0Bu6tMhLtD66DjB9u5l2CA2R4I/yyZ1h0B30REDvGDgVcpq54AbaazFHn0n1CLUrufbs+/AyA3N5g2cnPPj5Hh+g5Njm5S2wbdPCYTeiSi5BqVZIUPesX9QwWHyKOkcUpP3L4c1hgTnVCoEZWpXgcEyCUdanuM0VT3GTcgZJiRmhPHNudxs8+mIrn9A17UNutE2MBtBeKoYHBp0JyiDSyKOQd2Lt4Xg7BHVrCij6ACflmofEokJ8ZecaAvwpjsduDC03RrxCz74bVPBqVzwDBfuFInFhoR8DhWQ5vKB1b0lr6VGL4Y4fjBwDhwJTUcA6Dc1fMOUm5wyjv7nzBgOgteN6DU1AsOFmNENccf+jKnKCh/OFQ76sCi3HC4iS1zbNCfs05zQMGd4UdnRZkCv2REZBmDFqljSRymTKj8uJx+clvepPu2oC8w9P+wT8D/jhGhxoNeEAGbxORNQLM8zDTL5KJvpIQ07cKTtTQq8e40BzEJ3gmVNdamO+O/viFlU35YCM3r+aaL2CXxAZMx4ivjBNbtwzIsOZzUQvb9jZoloWPWmxaIDdzoB11zdcD2TWuva0fBk0MwSLt6U0moAkKby/SiXm0xORfZyt5pky2BW7032DZVf9ePDtrzxNRYJoxmWvWJ1aLMQpba+oWTJF/gJWd7kWAp1uxzVZm8nJgaDenl962PLGiDwt9PavpXuyaxsqQMJWxwtxs9u7Q8EzewYAq9tBbrXOcUs32YrGeFFFezW1LGiqTUC1vTKGodWeKWUUWyF3k7pK9xPMD+1OxBEfTpg1m9f4VOFfzD4p+DWL94vh3c3cOXu7i+uzbG9Pwrd6R8=</diagram></mxfile>

assets/options.gif

256 KB
Loading

asyncgit/src/diff.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
error::Result,
33
hash,
4-
sync::{self, CommitId},
4+
sync::{self, diff::DiffOptions, CommitId},
55
AsyncGitNotification, FileDiff, CWD,
66
};
77
use crossbeam_channel::Sender;
@@ -14,7 +14,7 @@ use std::{
1414
};
1515

1616
///
17-
#[derive(Hash, Clone, PartialEq)]
17+
#[derive(Debug, Hash, Clone, PartialEq)]
1818
pub enum DiffType {
1919
/// diff in a given commit
2020
Commit(CommitId),
@@ -25,12 +25,14 @@ pub enum DiffType {
2525
}
2626

2727
///
28-
#[derive(Hash, Clone, PartialEq)]
28+
#[derive(Debug, Hash, Clone, PartialEq)]
2929
pub struct DiffParams {
3030
/// path to the file to diff
3131
pub path: String,
3232
/// what kind of diff
3333
pub diff_type: DiffType,
34+
/// diff options
35+
pub options: DiffOptions,
3436
}
3537

3638
struct Request<R, A>(R, Option<A>);
@@ -87,7 +89,7 @@ impl AsyncDiff {
8789
&mut self,
8890
params: DiffParams,
8991
) -> Result<Option<FileDiff>> {
90-
log::trace!("request");
92+
log::trace!("request {:?}", params);
9193

9294
let hash = hash(&params);
9395

@@ -148,12 +150,18 @@ impl AsyncDiff {
148150
hash: u64,
149151
) -> Result<bool> {
150152
let res = match params.diff_type {
151-
DiffType::Stage => {
152-
sync::diff::get_diff(CWD, &params.path, true)?
153-
}
154-
DiffType::WorkDir => {
155-
sync::diff::get_diff(CWD, &params.path, false)?
156-
}
153+
DiffType::Stage => sync::diff::get_diff(
154+
CWD,
155+
&params.path,
156+
true,
157+
Some(params.options),
158+
)?,
159+
DiffType::WorkDir => sync::diff::get_diff(
160+
CWD,
161+
&params.path,
162+
false,
163+
Some(params.options),
164+
)?,
157165
DiffType::Commit(id) => sync::diff::get_diff_commit(
158166
CWD,
159167
id,

asyncgit/src/status.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
error::Result,
33
hash,
4-
sync::{self, status::StatusType},
4+
sync::{self, status::StatusType, ShowUntrackedFilesConfig},
55
AsyncGitNotification, StatusItem, CWD,
66
};
77
use crossbeam_channel::Sender;
@@ -31,14 +31,19 @@ pub struct Status {
3131
pub struct StatusParams {
3232
tick: u128,
3333
status_type: StatusType,
34+
config: Option<ShowUntrackedFilesConfig>,
3435
}
3536

3637
impl StatusParams {
3738
///
38-
pub fn new(status_type: StatusType) -> Self {
39+
pub fn new(
40+
status_type: StatusType,
41+
config: Option<ShowUntrackedFilesConfig>,
42+
) -> Self {
3943
Self {
4044
tick: current_tick(),
4145
status_type,
46+
config,
4247
}
4348
}
4449
}
@@ -109,12 +114,14 @@ impl AsyncStatus {
109114
let sender = self.sender.clone();
110115
let arc_pending = Arc::clone(&self.pending);
111116
let status_type = params.status_type;
117+
let config = params.config;
112118

113119
self.pending.fetch_add(1, Ordering::Relaxed);
114120

115121
rayon_core::spawn(move || {
116122
let ok = Self::fetch_helper(
117123
status_type,
124+
config,
118125
hash_request,
119126
&arc_current,
120127
&arc_last,
@@ -135,11 +142,12 @@ impl AsyncStatus {
135142

136143
fn fetch_helper(
137144
status_type: StatusType,
145+
config: Option<ShowUntrackedFilesConfig>,
138146
hash_request: u64,
139147
arc_current: &Arc<Mutex<Request<u64, Status>>>,
140148
arc_last: &Arc<Mutex<Status>>,
141149
) -> Result<()> {
142-
let res = Self::get_status(status_type)?;
150+
let res = Self::get_status(status_type, config)?;
143151
log::trace!(
144152
"status fetched: {} (type: {:?})",
145153
hash_request,
@@ -161,9 +169,16 @@ impl AsyncStatus {
161169
Ok(())
162170
}
163171

164-
fn get_status(status_type: StatusType) -> Result<Status> {
172+
fn get_status(
173+
status_type: StatusType,
174+
config: Option<ShowUntrackedFilesConfig>,
175+
) -> Result<Status> {
165176
Ok(Status {
166-
items: sync::status::get_status(CWD, status_type)?,
177+
items: sync::status::get_status(
178+
CWD,
179+
status_type,
180+
config,
181+
)?,
167182
})
168183
}
169184
}

asyncgit/src/sync/config.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use scopetime::scope_time;
55

66
// see https://git-scm.com/docs/git-config#Documentation/git-config.txt-statusshowUntrackedFiles
77
/// represents the `status.showUntrackedFiles` git config state
8+
#[derive(Hash, Copy, Clone, PartialEq)]
89
pub enum ShowUntrackedFilesConfig {
910
///
1011
No,
@@ -14,19 +15,25 @@ pub enum ShowUntrackedFilesConfig {
1415
All,
1516
}
1617

18+
impl Default for ShowUntrackedFilesConfig {
19+
fn default() -> Self {
20+
Self::No
21+
}
22+
}
23+
1724
impl ShowUntrackedFilesConfig {
1825
///
19-
pub const fn include_none(&self) -> bool {
26+
pub const fn include_none(self) -> bool {
2027
matches!(self, Self::No)
2128
}
2229

2330
///
24-
pub const fn include_untracked(&self) -> bool {
31+
pub const fn include_untracked(self) -> bool {
2532
matches!(self, Self::Normal | Self::All)
2633
}
2734

2835
///
29-
pub const fn recurse_untracked_dirs(&self) -> bool {
36+
pub const fn recurse_untracked_dirs(self) -> bool {
3037
matches!(self, Self::All)
3138
}
3239
}

asyncgit/src/sync/diff.rs

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use super::{
88
use crate::{error::Error, error::Result, hash};
99
use easy_cast::Conv;
1010
use git2::{
11-
Delta, Diff, DiffDelta, DiffFormat, DiffHunk, DiffOptions, Patch,
12-
Repository,
11+
Delta, Diff, DiffDelta, DiffFormat, DiffHunk, Patch, Repository,
1312
};
1413
use scopetime::scope_time;
1514
use std::{cell::RefCell, fs, path::Path, rc::Rc};
@@ -125,18 +124,41 @@ pub struct FileDiff {
125124
pub size_delta: i64,
126125
}
127126

127+
/// see <https://libgit2.org/libgit2/#HEAD/type/git_diff_options>
128+
#[derive(Debug, Hash, Clone, Copy, PartialEq)]
129+
pub struct DiffOptions {
130+
/// see <https://libgit2.org/libgit2/#HEAD/type/git_diff_options>
131+
pub ignore_whitespace: bool,
132+
/// see <https://libgit2.org/libgit2/#HEAD/type/git_diff_options>
133+
pub context: u32,
134+
/// see <https://libgit2.org/libgit2/#HEAD/type/git_diff_options>
135+
pub interhunk_lines: u32,
136+
}
137+
138+
impl Default for DiffOptions {
139+
fn default() -> Self {
140+
Self {
141+
ignore_whitespace: false,
142+
context: 3,
143+
interhunk_lines: 0,
144+
}
145+
}
146+
}
147+
128148
pub(crate) fn get_diff_raw<'a>(
129149
repo: &'a Repository,
130150
p: &str,
131151
stage: bool,
132152
reverse: bool,
133-
context: Option<u32>,
153+
options: Option<DiffOptions>,
134154
) -> Result<Diff<'a>> {
135155
// scope_time!("get_diff_raw");
136156

137-
let mut opt = DiffOptions::new();
138-
if let Some(context) = context {
139-
opt.context_lines(context);
157+
let mut opt = git2::DiffOptions::new();
158+
if let Some(options) = options {
159+
opt.context_lines(options.context);
160+
opt.ignore_whitespace(options.ignore_whitespace);
161+
opt.interhunk_lines(options.interhunk_lines);
140162
}
141163
opt.pathspec(p);
142164
opt.reverse(reverse);
@@ -173,12 +195,13 @@ pub fn get_diff(
173195
repo_path: &str,
174196
p: &str,
175197
stage: bool,
198+
options: Option<DiffOptions>,
176199
) -> Result<FileDiff> {
177200
scope_time!("get_diff");
178201

179202
let repo = utils::repo(repo_path)?;
180203
let work_dir = work_dir(&repo)?;
181-
let diff = get_diff_raw(&repo, p, stage, false, None)?;
204+
let diff = get_diff_raw(&repo, p, stage, false, options)?;
182205

183206
raw_diff_to_file_diff(&diff, work_dir)
184207
}
@@ -386,7 +409,8 @@ mod tests {
386409

387410
assert_eq!(get_statuses(repo_path), (1, 0));
388411

389-
let diff = get_diff(repo_path, "foo/bar.txt", false).unwrap();
412+
let diff =
413+
get_diff(repo_path, "foo/bar.txt", false, None).unwrap();
390414

391415
assert_eq!(diff.hunks.len(), 1);
392416
assert_eq!(diff.hunks[0].lines[1].content, "test\n");
@@ -412,9 +436,13 @@ mod tests {
412436

413437
assert_eq!(get_statuses(repo_path), (0, 1));
414438

415-
let diff =
416-
get_diff(repo_path, file_path.to_str().unwrap(), true)
417-
.unwrap();
439+
let diff = get_diff(
440+
repo_path,
441+
file_path.to_str().unwrap(),
442+
true,
443+
None,
444+
)
445+
.unwrap();
418446

419447
assert_eq!(diff.hunks.len(), 1);
420448
}
@@ -462,8 +490,8 @@ mod tests {
462490
.unwrap();
463491
}
464492

465-
let res =
466-
get_status(repo_path, StatusType::WorkingDir).unwrap();
493+
let res = get_status(repo_path, StatusType::WorkingDir, None)
494+
.unwrap();
467495
assert_eq!(res.len(), 1);
468496
assert_eq!(res[0].path, "bar.txt");
469497

@@ -480,7 +508,8 @@ mod tests {
480508

481509
assert_eq!(get_statuses(repo_path), (1, 1));
482510

483-
let res = get_diff(repo_path, "bar.txt", false).unwrap();
511+
let res =
512+
get_diff(repo_path, "bar.txt", false, None).unwrap();
484513

485514
assert_eq!(res.hunks.len(), 2)
486515
}
@@ -503,6 +532,7 @@ mod tests {
503532
sub_path.to_str().unwrap(),
504533
file_path.to_str().unwrap(),
505534
false,
535+
None,
506536
)
507537
.unwrap();
508538

@@ -525,9 +555,13 @@ mod tests {
525555
File::create(&root.join(file_path))?
526556
.write_all(b"\x00\x02")?;
527557

528-
let diff =
529-
get_diff(repo_path, file_path.to_str().unwrap(), false)
530-
.unwrap();
558+
let diff = get_diff(
559+
repo_path,
560+
file_path.to_str().unwrap(),
561+
false,
562+
None,
563+
)
564+
.unwrap();
531565

532566
dbg!(&diff);
533567
assert_eq!(diff.sizes, (1, 2));
@@ -546,9 +580,13 @@ mod tests {
546580
File::create(&root.join(file_path))?
547581
.write_all(b"\x00\xc7")?;
548582

549-
let diff =
550-
get_diff(repo_path, file_path.to_str().unwrap(), false)
551-
.unwrap();
583+
let diff = get_diff(
584+
repo_path,
585+
file_path.to_str().unwrap(),
586+
false,
587+
None,
588+
)
589+
.unwrap();
552590

553591
dbg!(&diff);
554592
assert_eq!(diff.sizes, (0, 2));

asyncgit/src/sync/hunks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ mod tests {
173173
sub_path.to_str().unwrap(),
174174
file_path.to_str().unwrap(),
175175
false,
176+
None,
176177
)?;
177178

178179
assert!(reset_hunk(

asyncgit/src/sync/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,12 @@ mod tests {
255255
/// helper returning amount of files with changes in the (wd,stage)
256256
pub fn get_statuses(repo_path: &str) -> (usize, usize) {
257257
(
258-
get_status(repo_path, StatusType::WorkingDir)
258+
get_status(repo_path, StatusType::WorkingDir, None)
259+
.unwrap()
260+
.len(),
261+
get_status(repo_path, StatusType::Stage, None)
259262
.unwrap()
260263
.len(),
261-
get_status(repo_path, StatusType::Stage).unwrap().len(),
262264
)
263265
}
264266

0 commit comments

Comments
 (0)