1
1
use super :: { stash:: is_stash_commit, utils:: repo, CommitId } ;
2
- use crate :: { error:: Result , StatusItem , StatusItemType , CWD } ;
2
+ use crate :: { error:: Result , StatusItem , StatusItemType } ;
3
3
use git2:: { Diff , DiffDelta , DiffOptions , Repository } ;
4
4
use scopetime:: scope_time;
5
5
@@ -33,22 +33,6 @@ pub fn get_commit_files(
33
33
None ,
34
34
) ?;
35
35
36
- // stash commits have parent commits containing untracked files and if we want to show
37
- // these files as if they were actually in the stash commit we have to have some specific
38
- // handling regarding these special stash commits.
39
- // more info can be found at https://stackoverflow.com/questions/51275777/why-does-git-stash-pop-say-that-it-could-not-restore-untracked-files-from-stash/51276389#51276389
40
- if is_stash_commit ( repo_path, & id) ? {
41
- let commit = repo. find_commit ( id. into ( ) ) ?;
42
- let untracked_commit = commit. parent_id ( 2 ) ?;
43
-
44
- let mut untracked_files = get_commit_files (
45
- repo_path,
46
- CommitId :: new ( untracked_commit) ,
47
- ) ?;
48
-
49
- res. append ( & mut untracked_files) ;
50
- }
51
-
52
36
Ok ( res)
53
37
}
54
38
@@ -75,20 +59,25 @@ pub(crate) fn get_commit_diff(
75
59
opts
76
60
} ) ;
77
61
78
- let diff = repo. diff_tree_to_tree (
62
+ let mut diff = repo. diff_tree_to_tree (
79
63
parent. as_ref ( ) ,
80
64
Some ( & commit_tree) ,
81
65
opt. as_mut ( ) ,
82
66
) ?;
83
67
84
- if diff. deltas ( ) . len ( ) == 0 && is_stash_commit ( CWD , & id) ? {
68
+ if is_stash_commit (
69
+ repo. path ( ) . to_str ( ) . expect ( "repo path utf8 err" ) ,
70
+ & id,
71
+ ) ? {
85
72
let untracked_commit = commit. parent_id ( 2 ) ?;
86
73
87
- return get_commit_diff (
74
+ let untracked_diff = get_commit_diff (
88
75
repo,
89
76
CommitId :: new ( untracked_commit) ,
90
77
pathspec,
91
- ) ;
78
+ ) ?;
79
+
80
+ diff. merge ( & untracked_diff) ?;
92
81
}
93
82
94
83
Ok ( diff)
@@ -100,7 +89,8 @@ mod tests {
100
89
use crate :: {
101
90
error:: Result ,
102
91
sync:: {
103
- commit, stage_add_file, stash_save, tests:: repo_init,
92
+ commit, stage_add_file, stash_save,
93
+ tests:: { get_statuses, repo_init} ,
104
94
} ,
105
95
StatusItemType ,
106
96
} ;
@@ -140,14 +130,40 @@ mod tests {
140
130
141
131
let id = stash_save ( repo_path, None , true , false ) ?;
142
132
143
- //TODO: https://github.com/extrawurst/gitui/issues/130
144
- // `get_commit_diff` actually needs to merge the regular diff
145
- // and a third parent diff containing the untracked files
146
133
let diff = get_commit_files ( repo_path, id) ?;
147
134
148
135
assert_eq ! ( diff. len( ) , 1 ) ;
149
136
assert_eq ! ( diff[ 0 ] . status, StatusItemType :: New ) ;
150
137
151
138
Ok ( ( ) )
152
139
}
140
+
141
+ #[ test]
142
+ fn test_stashed_untracked_and_modified ( ) -> Result < ( ) > {
143
+ let file_path1 = Path :: new ( "file1.txt" ) ;
144
+ let file_path2 = Path :: new ( "file2.txt" ) ;
145
+ let ( _td, repo) = repo_init ( ) ?;
146
+ let root = repo. path ( ) . parent ( ) . unwrap ( ) ;
147
+ let repo_path = root. as_os_str ( ) . to_str ( ) . unwrap ( ) ;
148
+
149
+ File :: create ( & root. join ( file_path1) ) ?. write_all ( b"test" ) ?;
150
+ stage_add_file ( repo_path, file_path1) ?;
151
+ commit ( repo_path, "c1" ) ?;
152
+
153
+ File :: create ( & root. join ( file_path1) ) ?
154
+ . write_all ( b"modified" ) ?;
155
+ File :: create ( & root. join ( file_path2) ) ?. write_all ( b"new" ) ?;
156
+
157
+ assert_eq ! ( get_statuses( repo_path) , ( 2 , 0 ) ) ;
158
+
159
+ let id = stash_save ( repo_path, None , true , false ) ?;
160
+
161
+ let diff = get_commit_files ( repo_path, id) ?;
162
+
163
+ assert_eq ! ( diff. len( ) , 2 ) ;
164
+ assert_eq ! ( diff[ 0 ] . status, StatusItemType :: Modified ) ;
165
+ assert_eq ! ( diff[ 1 ] . status, StatusItemType :: New ) ;
166
+
167
+ Ok ( ( ) )
168
+ }
153
169
}
0 commit comments