@@ -20,6 +20,42 @@ public void CanRetrieveTheStatusOfAFile()
20
20
}
21
21
}
22
22
23
+ [ Theory ]
24
+ [ InlineData ( StatusShowOption . IndexAndWorkDir , FileStatus . Untracked ) ]
25
+ [ InlineData ( StatusShowOption . WorkDirOnly , FileStatus . Untracked ) ]
26
+ [ InlineData ( StatusShowOption . IndexOnly , FileStatus . Nonexistent ) ]
27
+ public void CanLimitStatusToWorkDirOnly ( StatusShowOption show , FileStatus expected )
28
+ {
29
+ var clone = CloneStandardTestRepo ( ) ;
30
+
31
+ using ( var repo = new Repository ( clone ) )
32
+ {
33
+ Touch ( repo . Info . WorkingDirectory , "file.txt" , "content" ) ;
34
+
35
+ RepositoryStatus status = repo . Index . RetrieveStatus ( new StatusOptions ( ) { Show = show } ) ;
36
+ Assert . Equal ( expected , status [ "file.txt" ] . State ) ;
37
+ }
38
+ }
39
+
40
+ [ Theory ]
41
+ [ InlineData ( StatusShowOption . IndexAndWorkDir , FileStatus . Added ) ]
42
+ [ InlineData ( StatusShowOption . WorkDirOnly , FileStatus . Nonexistent ) ]
43
+ [ InlineData ( StatusShowOption . IndexOnly , FileStatus . Added ) ]
44
+ public void CanLimitStatusToIndexOnly ( StatusShowOption show , FileStatus expected )
45
+ {
46
+ var clone = CloneStandardTestRepo ( ) ;
47
+
48
+ using ( var repo = new Repository ( clone ) )
49
+ {
50
+ Touch ( repo . Info . WorkingDirectory , "file.txt" , "content" ) ;
51
+ repo . Index . Stage ( "file.txt" ) ;
52
+
53
+ RepositoryStatus status = repo . Index . RetrieveStatus ( new StatusOptions ( ) { Show = show } ) ;
54
+ Assert . Equal ( expected , status [ "file.txt" ] . State ) ;
55
+ }
56
+ }
57
+
58
+
23
59
[ Theory ]
24
60
[ InlineData ( "file" ) ]
25
61
[ InlineData ( "file.txt" ) ]
@@ -75,37 +111,132 @@ public void CanRetrieveTheStatusOfTheWholeWorkingDirectory()
75
111
76
112
RepositoryStatus status = repo . Index . RetrieveStatus ( ) ;
77
113
78
- Assert . Equal ( FileStatus . Staged , status [ file ] ) ;
114
+ Assert . Equal ( FileStatus . Staged , status [ file ] . State ) ;
79
115
80
116
Assert . NotNull ( status ) ;
81
117
Assert . Equal ( 6 , status . Count ( ) ) ;
82
118
Assert . True ( status . IsDirty ) ;
83
119
84
- Assert . Equal ( "new_untracked_file.txt" , status . Untracked . Single ( ) ) ;
85
- Assert . Equal ( "modified_unstaged_file.txt" , status . Modified . Single ( ) ) ;
86
- Assert . Equal ( "deleted_unstaged_file.txt" , status . Missing . Single ( ) ) ;
87
- Assert . Equal ( "new_tracked_file.txt" , status . Added . Single ( ) ) ;
88
- Assert . Equal ( file , status . Staged . Single ( ) ) ;
89
- Assert . Equal ( "deleted_staged_file.txt" , status . Removed . Single ( ) ) ;
120
+ Assert . Equal ( "new_untracked_file.txt" , status . Untracked . Select ( s => s . FilePath ) . Single ( ) ) ;
121
+ Assert . Equal ( "modified_unstaged_file.txt" , status . Modified . Select ( s => s . FilePath ) . Single ( ) ) ;
122
+ Assert . Equal ( "deleted_unstaged_file.txt" , status . Missing . Select ( s => s . FilePath ) . Single ( ) ) ;
123
+ Assert . Equal ( "new_tracked_file.txt" , status . Added . Select ( s => s . FilePath ) . Single ( ) ) ;
124
+ Assert . Equal ( file , status . Staged . Select ( s => s . FilePath ) . Single ( ) ) ;
125
+ Assert . Equal ( "deleted_staged_file.txt" , status . Removed . Select ( s => s . FilePath ) . Single ( ) ) ;
90
126
91
127
File . AppendAllText ( Path . Combine ( repo . Info . WorkingDirectory , file ) ,
92
128
"Tclem's favorite commit message: boom" ) ;
93
129
94
130
Assert . Equal ( FileStatus . Staged | FileStatus . Modified , repo . Index . RetrieveStatus ( file ) ) ;
95
131
96
132
RepositoryStatus status2 = repo . Index . RetrieveStatus ( ) ;
97
- Assert . Equal ( FileStatus . Staged | FileStatus . Modified , status2 [ file ] ) ;
133
+ Assert . Equal ( FileStatus . Staged | FileStatus . Modified , status2 [ file ] . State ) ;
98
134
99
135
Assert . NotNull ( status2 ) ;
100
136
Assert . Equal ( 6 , status2 . Count ( ) ) ;
101
137
Assert . True ( status2 . IsDirty ) ;
102
138
103
- Assert . Equal ( "new_untracked_file.txt" , status2 . Untracked . Single ( ) ) ;
104
- Assert . Equal ( new [ ] { file , "modified_unstaged_file.txt" } , status2 . Modified ) ;
105
- Assert . Equal ( "deleted_unstaged_file.txt" , status2 . Missing . Single ( ) ) ;
106
- Assert . Equal ( "new_tracked_file.txt" , status2 . Added .Single ( ) ) ;
107
- Assert . Equal ( file , status2 . Staged . Single ( ) ) ;
108
- Assert . Equal ( "deleted_staged_file.txt" , status2 . Removed . Single ( ) ) ;
139
+ Assert . Equal ( "new_untracked_file.txt" , status2 . Untracked . Select ( s => s . FilePath ) . Single ( ) ) ;
140
+ Assert . Equal ( new [ ] { file , "modified_unstaged_file.txt" } , status2 . Modified . Select ( s => s . FilePath ) ) ;
141
+ Assert . Equal ( "deleted_unstaged_file.txt" , status2 . Missing . Select ( s => s . FilePath ) . Single ( ) ) ;
142
+ Assert . Equal ( "new_tracked_file.txt" , status2 . Added . Select ( s => s . FilePath ) . Single ( ) ) ;
143
+ Assert . Equal ( file , status2 . Staged . Select ( s => s . FilePath ) . Single ( ) ) ;
144
+ Assert . Equal ( "deleted_staged_file.txt" , status2 . Removed . Select ( s => s . FilePath ) . Single ( ) ) ;
145
+ }
146
+ }
147
+
148
+ [ Fact ]
149
+ public void CanRetrieveTheStatusOfRenamedFilesInWorkDir ( )
150
+ {
151
+ string path = CloneStandardTestRepo ( ) ;
152
+ using ( var repo = new Repository ( path ) )
153
+ {
154
+ Touch ( repo . Info . WorkingDirectory , "old_name.txt" ,
155
+ "This is a file with enough data to trigger similarity matching.\r \n " +
156
+ "This is a file with enough data to trigger similarity matching.\r \n " +
157
+ "This is a file with enough data to trigger similarity matching.\r \n " +
158
+ "This is a file with enough data to trigger similarity matching.\r \n " ) ;
159
+
160
+ repo . Index . Stage ( "old_name.txt" ) ;
161
+
162
+ File . Move ( Path . Combine ( repo . Info . WorkingDirectory , "old_name.txt" ) ,
163
+ Path . Combine ( repo . Info . WorkingDirectory , "rename_target.txt" ) ) ;
164
+
165
+ RepositoryStatus status = repo . Index . RetrieveStatus (
166
+ new StatusOptions ( )
167
+ {
168
+ DetectRenamesInIndex = true ,
169
+ DetectRenamesInWorkDir = true
170
+ } ) ;
171
+
172
+ Assert . Equal ( FileStatus . Added | FileStatus . RenamedInWorkDir , status [ "rename_target.txt" ] . State ) ;
173
+ Assert . Equal ( 100 , status [ "rename_target.txt" ] . IndexToWorkDirRenameDetails . Similarity ) ;
174
+ }
175
+ }
176
+
177
+ [ Fact ]
178
+ public void CanRetrieveTheStatusOfRenamedFilesInIndex ( )
179
+ {
180
+ string path = CloneStandardTestRepo ( ) ;
181
+ using ( var repo = new Repository ( path ) )
182
+ {
183
+ File . Move (
184
+ Path . Combine ( repo . Info . WorkingDirectory , "1.txt" ) ,
185
+ Path . Combine ( repo . Info . WorkingDirectory , "rename_target.txt" ) ) ;
186
+
187
+ repo . Index . Stage ( "1.txt" ) ;
188
+ repo . Index . Stage ( "rename_target.txt" ) ;
189
+
190
+ RepositoryStatus status = repo . Index . RetrieveStatus ( ) ;
191
+
192
+ Assert . Equal ( FileStatus . RenamedInIndex , status [ "rename_target.txt" ] . State ) ;
193
+ Assert . Equal ( 100 , status [ "rename_target.txt" ] . HeadToIndexRenameDetails . Similarity ) ;
194
+ }
195
+ }
196
+
197
+ [ Fact ]
198
+ public void CanDetectedVariousKindsOfRenaming ( )
199
+ {
200
+ string path = InitNewRepository ( ) ;
201
+ using ( var repo = new Repository ( path ) )
202
+ {
203
+ Touch ( repo . Info . WorkingDirectory , "file.txt" ,
204
+ "This is a file with enough data to trigger similarity matching.\r \n " +
205
+ "This is a file with enough data to trigger similarity matching.\r \n " +
206
+ "This is a file with enough data to trigger similarity matching.\r \n " +
207
+ "This is a file with enough data to trigger similarity matching.\r \n " ) ;
208
+
209
+ repo . Index . Stage ( "file.txt" ) ;
210
+ repo . Commit ( "Initial commit" , Constants . Signature , Constants . Signature ) ;
211
+
212
+ File . Move ( Path . Combine ( repo . Info . WorkingDirectory , "file.txt" ) ,
213
+ Path . Combine ( repo . Info . WorkingDirectory , "renamed.txt" ) ) ;
214
+
215
+ var opts = new StatusOptions
216
+ {
217
+ DetectRenamesInIndex = true ,
218
+ DetectRenamesInWorkDir = true
219
+ } ;
220
+
221
+ RepositoryStatus status = repo . Index . RetrieveStatus ( opts ) ;
222
+
223
+ // This passes as expected
224
+ Assert . Equal ( FileStatus . RenamedInWorkDir , status . Single ( ) . State ) ;
225
+
226
+ repo . Index . Stage ( "file.txt" ) ;
227
+ repo . Index . Stage ( "renamed.txt" ) ;
228
+
229
+ status = repo . Index . RetrieveStatus ( opts ) ;
230
+
231
+ Assert . Equal ( FileStatus . RenamedInIndex , status . Single ( ) . State ) ;
232
+
233
+ File . Move ( Path . Combine ( repo . Info . WorkingDirectory , "renamed.txt" ) ,
234
+ Path . Combine ( repo . Info . WorkingDirectory , "renamed_again.txt" ) ) ;
235
+
236
+ status = repo . Index . RetrieveStatus ( opts ) ;
237
+
238
+ Assert . Equal ( FileStatus . RenamedInWorkDir | FileStatus . RenamedInIndex ,
239
+ status . Single ( ) . State ) ;
109
240
}
110
241
}
111
242
@@ -154,7 +285,7 @@ public void RetrievingTheStatusOfARepositoryReturnNativeFilePaths()
154
285
155
286
Assert . Equal ( relFilePath , statusEntry . FilePath ) ;
156
287
157
- Assert . Equal ( statusEntry . FilePath , repoStatus . Added . Single ( ) ) ;
288
+ Assert . Equal ( statusEntry . FilePath , repoStatus . Added . Select ( s => s . FilePath ) . Single ( ) ) ;
158
289
}
159
290
}
160
291
@@ -169,15 +300,15 @@ public void RetrievingTheStatusOfAnEmptyRepositoryHonorsTheGitIgnoreDirectives()
169
300
Touch ( repo . Info . WorkingDirectory , relativePath , "I'm going to be ignored!" ) ;
170
301
171
302
RepositoryStatus status = repo . Index . RetrieveStatus ( ) ;
172
- Assert . Equal ( new [ ] { relativePath } , status . Untracked ) ;
303
+ Assert . Equal ( new [ ] { relativePath } , status . Untracked . Select ( s => s . FilePath ) ) ;
173
304
174
305
Touch ( repo . Info . WorkingDirectory , ".gitignore" , "*.txt" + Environment . NewLine ) ;
175
306
176
307
RepositoryStatus newStatus = repo . Index . RetrieveStatus ( ) ;
177
- Assert . Equal ( ".gitignore" , newStatus . Untracked . Single ( ) ) ;
308
+ Assert . Equal ( ".gitignore" , newStatus . Untracked . Select ( s => s . FilePath ) . Single ( ) ) ;
178
309
179
310
Assert . Equal ( FileStatus . Ignored , repo . Index . RetrieveStatus ( relativePath ) ) ;
180
- Assert . Equal ( new [ ] { relativePath } , newStatus . Ignored ) ;
311
+ Assert . Equal ( new [ ] { relativePath } , newStatus . Ignored . Select ( s => s . FilePath ) ) ;
181
312
}
182
313
}
183
314
@@ -223,7 +354,7 @@ public void RetrievingTheStatusOfTheRepositoryHonorsTheGitIgnoreDirectives()
223
354
224
355
RepositoryStatus status = repo . Index . RetrieveStatus ( ) ;
225
356
226
- Assert . Equal ( new [ ] { relativePath , "new_untracked_file.txt" } , status . Untracked ) ;
357
+ Assert . Equal ( new [ ] { relativePath , "new_untracked_file.txt" } , status . Untracked . Select ( s => s . FilePath ) ) ;
227
358
228
359
Touch ( repo . Info . WorkingDirectory , ".gitignore" , "*.txt" + Environment . NewLine ) ;
229
360
@@ -263,10 +394,10 @@ public void RetrievingTheStatusOfTheRepositoryHonorsTheGitIgnoreDirectives()
263
394
*/
264
395
265
396
RepositoryStatus newStatus = repo . Index . RetrieveStatus ( ) ;
266
- Assert . Equal ( ".gitignore" , newStatus . Untracked . Single ( ) ) ;
397
+ Assert . Equal ( ".gitignore" , newStatus . Untracked . Select ( s => s . FilePath ) . Single ( ) ) ;
267
398
268
399
Assert . Equal ( FileStatus . Ignored , repo . Index . RetrieveStatus ( relativePath ) ) ;
269
- Assert . Equal ( new [ ] { relativePath , "new_untracked_file.txt" } , newStatus . Ignored ) ;
400
+ Assert . Equal ( new [ ] { relativePath , "new_untracked_file.txt" } , newStatus . Ignored . Select ( s => s . FilePath ) ) ;
270
401
}
271
402
}
272
403
@@ -354,7 +485,7 @@ public void RetrievingTheStatusOfTheRepositoryHonorsTheGitIgnoreDirectivesThroug
354
485
Assert . Equal ( FileStatus . Ignored , repo . Index . RetrieveStatus ( "bin/what-about-me.txt" ) ) ;
355
486
356
487
RepositoryStatus newStatus = repo . Index . RetrieveStatus ( ) ;
357
- Assert . Equal ( new [ ] { "bin" + dirSep } , newStatus . Ignored ) ;
488
+ Assert . Equal ( new [ ] { "bin" + dirSep } , newStatus . Ignored . Select ( s => s . FilePath ) ) ;
358
489
359
490
var sb = new StringBuilder ( ) ;
360
491
sb . AppendLine ( "bin/*" ) ;
@@ -366,8 +497,43 @@ public void RetrievingTheStatusOfTheRepositoryHonorsTheGitIgnoreDirectivesThroug
366
497
367
498
newStatus = repo . Index . RetrieveStatus ( ) ;
368
499
369
- Assert . Equal ( new [ ] { "bin" + dirSep + "look-ma.txt" } , newStatus . Ignored ) ;
370
- Assert . True ( newStatus . Untracked . Contains ( "bin" + dirSep + "what-about-me.txt" ) ) ;
500
+ Assert . Equal ( new [ ] { "bin" + dirSep + "look-ma.txt" } , newStatus . Ignored . Select ( s => s . FilePath ) ) ;
501
+ Assert . True ( newStatus . Untracked . Select ( s => s . FilePath ) . Contains ( "bin" + dirSep + "what-about-me.txt" ) ) ;
502
+ }
503
+ }
504
+
505
+ [ Fact ]
506
+ public void CanRetrieveStatusOfFilesInSubmodule ( )
507
+ {
508
+ var path = CloneSubmoduleTestRepo ( ) ;
509
+ using ( var repo = new Repository ( path ) )
510
+ {
511
+ string [ ] expected = new string [ ] {
512
+ ".gitmodules" ,
513
+ "sm_changed_file" ,
514
+ "sm_changed_head" ,
515
+ "sm_changed_index" ,
516
+ "sm_changed_untracked_file" ,
517
+ "sm_missing_commits"
518
+ } ;
519
+
520
+ RepositoryStatus status = repo . Index . RetrieveStatus ( ) ;
521
+ Assert . Equal ( expected , status . Modified . Select ( x => x . FilePath ) . ToArray ( ) ) ;
522
+ }
523
+ }
524
+
525
+ [ Fact ]
526
+ public void CanExcludeStatusOfFilesInSubmodule ( )
527
+ {
528
+ var path = CloneSubmoduleTestRepo ( ) ;
529
+ using ( var repo = new Repository ( path ) )
530
+ {
531
+ string [ ] expected = new string [ ] {
532
+ ".gitmodules" ,
533
+ } ;
534
+
535
+ RepositoryStatus status = repo . Index . RetrieveStatus ( new StatusOptions ( ) { ExcludeSubmodules = true } ) ;
536
+ Assert . Equal ( expected , status . Modified . Select ( x => x . FilePath ) . ToArray ( ) ) ;
371
537
}
372
538
}
373
539
}
0 commit comments