4
4
using System . Globalization ;
5
5
using System . IO ;
6
6
using LibGit2Sharp . Core ;
7
+ using LibGit2Sharp . Core . Compat ;
7
8
8
9
namespace LibGit2Sharp
9
10
{
@@ -118,36 +119,16 @@ IEnumerator IEnumerable.GetEnumerator()
118
119
/// <summary>
119
120
/// Promotes to the staging area the latest modifications of a file in the working directory (addition, updation or removal).
120
121
/// </summary>
121
- /// <param name= "path">The relative path within the working directory to the file .</param>
122
+ /// <param name = "path">The path of the file within the working directory .</param>
122
123
public void Stage ( string path )
123
124
{
124
- Ensure . ArgumentNotNullOrEmptyString ( path , "path" ) ;
125
-
126
- string relativePath = BuildRelativePathFrom ( repo , path ) ;
127
-
128
- FileStatus fileStatus = RetrieveStatus ( relativePath ) ;
129
-
130
- if ( fileStatus . Has ( FileStatus . Nonexistent ) )
131
- {
132
- throw new LibGit2Exception ( "Can not stage '{0}'. The file does not exist." ) ;
133
- }
134
-
135
- if ( fileStatus . Has ( FileStatus . Missing ) )
136
- {
137
- RemoveFromIndex ( relativePath ) ;
138
- }
139
- else
140
- {
141
- AddToIndex ( relativePath ) ;
142
- }
143
-
144
- UpdatePhysicalIndex ( ) ;
125
+ Stage ( new [ ] { path } ) ;
145
126
}
146
127
147
128
/// <summary>
148
129
/// Promotes to the staging area the latest modifications of a collection of files in the working directory (addition, updation or removal).
149
130
/// </summary>
150
- /// <param name= "paths">The collection of paths within the working directory to the files .</param>
131
+ /// <param name = "paths">The collection of paths of the files within the working directory .</param>
151
132
public void Stage ( IEnumerable < string > paths )
152
133
{
153
134
Ensure . ArgumentNotNull ( paths , "paths" ) ;
@@ -190,36 +171,16 @@ public void Stage(IEnumerable<string> paths)
190
171
/// <summary>
191
172
/// Removes from the staging area all the modifications of a file since the latest commit (addition, updation or removal).
192
173
/// </summary>
193
- /// <param name= "path">The relative path within the working directory to the file .</param>
174
+ /// <param name = "path">The path of the file within the working directory .</param>
194
175
public void Unstage ( string path )
195
176
{
196
- Ensure . ArgumentNotNullOrEmptyString ( path , "path" ) ;
197
-
198
- string relativePath = BuildRelativePathFrom ( repo , path ) ;
199
-
200
- FileStatus fileStatus = RetrieveStatus ( relativePath ) ;
201
-
202
- bool doesExistInindex =
203
- ! ( fileStatus . Has ( FileStatus . Nonexistent ) || fileStatus . Has ( FileStatus . Removed ) ||
204
- fileStatus . Has ( FileStatus . Untracked ) ) ;
205
-
206
- if ( doesExistInindex )
207
- {
208
- RemoveFromIndex ( relativePath ) ;
209
- }
210
-
211
- bool doesExistInWorkingDirectory =
212
- ! ( fileStatus . Has ( FileStatus . Removed ) || fileStatus . Has ( FileStatus . Nonexistent ) ||
213
- fileStatus . Has ( FileStatus . Missing ) ) ;
214
- RestorePotentialPreviousVersionOfHeadIntoIndex ( relativePath , doesExistInWorkingDirectory ) ;
215
-
216
- UpdatePhysicalIndex ( ) ;
177
+ Unstage ( new [ ] { path } ) ;
217
178
}
218
179
219
180
/// <summary>
220
181
/// Removes from the staging area all the modifications of a collection of file since the latest commit (addition, updation or removal).
221
182
/// </summary>
222
- /// <param name= "paths">The collection of paths within the working directory to the files .</param>
183
+ /// <param name = "paths">The collection of paths of the files within the working directory .</param>
223
184
public void Unstage ( IEnumerable < string > paths )
224
185
{
225
186
Ensure . ArgumentNotNull ( paths , "paths" ) ;
@@ -254,75 +215,54 @@ public void Unstage(IEnumerable<string> paths)
254
215
/// <summary>
255
216
/// Moves and/or renames a file in the working directory and promotes the change to the staging area.
256
217
/// </summary>
257
- /// <param name= "sourcePath">The relative path within the working directory to the file which has to be moved/renamed.</param>
258
- /// <param name= "destinationPath">The target relative path within the working directory of the file .</param>
218
+ /// <param name = "sourcePath">The path of the file within the working directory which has to be moved/renamed.</param>
219
+ /// <param name = "destinationPath">The target path of the file within the working directory .</param>
259
220
public void Move ( string sourcePath , string destinationPath )
260
221
{
261
- Ensure . ArgumentNotNullOrEmptyString ( sourcePath , "sourcepath" ) ;
262
- Ensure . ArgumentNotNullOrEmptyString ( destinationPath , "destinationpath" ) ;
263
-
264
- string relativeSourcePath = BuildRelativePathFrom ( repo , sourcePath ) ;
265
- string relativeDestinationPath = BuildRelativePathFrom ( repo , destinationPath ) ;
266
-
267
- string wd = repo . Info . WorkingDirectory ;
268
- if ( Directory . Exists ( Path . Combine ( wd , relativeSourcePath ) ) )
269
- {
270
- throw new NotImplementedException ( ) ;
271
- }
272
-
273
- RemoveFromIndex ( relativeSourcePath ) ;
274
-
275
- File . Move ( Path . Combine ( wd , relativeSourcePath ) , Path . Combine ( wd , relativeDestinationPath ) ) ;
276
-
277
- AddToIndex ( relativeDestinationPath ) ;
278
-
279
- UpdatePhysicalIndex ( ) ;
222
+ Move ( new [ ] { sourcePath } , new [ ] { destinationPath } ) ;
280
223
}
281
224
282
225
/// <summary>
283
- /// Moves and/or renames a file in the working directory and promotes the change to the staging area.
226
+ /// Moves and/or renames a collection of files in the working directory and promotes the changes to the staging area.
284
227
/// </summary>
285
- /// <param name= "sourcePaths">The relative paths within the working directory to the files which has to be moved/renamed.</param>
286
- /// <param name= "destinationPaths">The target relative paths within the working directory of the files .</param>
228
+ /// <param name = "sourcePaths">The paths of the files within the working directory which have to be moved/renamed.</param>
229
+ /// <param name = "destinationPaths">The target paths of the files within the working directory .</param>
287
230
public void Move ( IEnumerable < string > sourcePaths , IEnumerable < string > destinationPaths )
288
231
{
289
232
Ensure . ArgumentNotNull ( sourcePaths , "sourcePaths" ) ;
290
233
Ensure . ArgumentNotNull ( destinationPaths , "destinationPaths" ) ;
291
234
292
- List < string > sourcePathsList = new List < string > ( ) ;
293
- List < string > destinationPathsList = new List < string > ( ) ;
235
+ IDictionary < Tuple < string , FileStatus > , Tuple < string , FileStatus > > batch = PrepareBatch ( sourcePaths , destinationPaths ) ;
294
236
295
- foreach ( string sourcePath in sourcePaths )
296
- {
297
- sourcePathsList . Add ( BuildRelativePathFrom ( repo , sourcePath ) ) ;
298
- }
299
- foreach ( string destinationPath in destinationPaths )
237
+ if ( batch . Count == 0 )
300
238
{
301
- destinationPathsList . Add ( BuildRelativePathFrom ( repo , destinationPath ) ) ;
239
+ throw new ArgumentNullException ( "sourcePaths" ) ;
302
240
}
303
241
304
- if ( sourcePathsList . Count != destinationPathsList . Count )
242
+ foreach ( KeyValuePair < Tuple < string , FileStatus > , Tuple < string , FileStatus > > keyValuePair in batch )
305
243
{
306
- throw new ArgumentException ( "The collection of paths are of different lengths" ) ;
307
- }
308
-
309
- string wd = repo . Info . WorkingDirectory ;
244
+ if ( keyValuePair . Key . Item2 . HasAny ( new [ ] { FileStatus . Nonexistent , FileStatus . Removed , FileStatus . Untracked , FileStatus . Missing } ) )
245
+ {
246
+ throw new LibGit2Exception ( string . Format ( "Unable to move file '{0}'. Its current status is '{1}'." , keyValuePair . Key . Item1 , Enum . GetName ( typeof ( FileStatus ) , keyValuePair . Key . Item2 ) ) ) ;
247
+ }
310
248
311
- foreach ( string relativeSourcePath in sourcePathsList )
312
- {
313
- if ( Directory . Exists ( Path . Combine ( wd , relativeSourcePath ) ) )
249
+ if ( keyValuePair . Value . Item2 . Has ( FileStatus . Nonexistent ) )
314
250
{
315
- throw new NotImplementedException ( ) ;
251
+ continue ;
316
252
}
253
+
254
+ throw new LibGit2Exception ( string . Format ( "Unable to overwrite file '{0}'. Its current status is '{1}'." , keyValuePair . Value . Item1 , Enum . GetName ( typeof ( FileStatus ) , keyValuePair . Value . Item2 ) ) ) ;
317
255
}
318
256
319
- for ( int i = 0 ; i < sourcePathsList . Count ; i ++ )
257
+ string wd = repo . Info . WorkingDirectory ;
258
+ foreach ( KeyValuePair < Tuple < string , FileStatus > , Tuple < string , FileStatus > > keyValuePair in batch )
320
259
{
321
- RemoveFromIndex ( sourcePathsList [ i ] ) ;
260
+ string from = keyValuePair . Key . Item1 ;
261
+ string to = keyValuePair . Value . Item1 ;
322
262
323
- File . Move ( Path . Combine ( wd , sourcePathsList [ i ] ) , Path . Combine ( wd , destinationPathsList [ i ] ) ) ;
324
-
325
- AddToIndex ( destinationPathsList [ i ] ) ;
263
+ RemoveFromIndex ( from ) ;
264
+ File . Move ( Path . Combine ( wd , from ) , Path . Combine ( wd , to ) ) ;
265
+ AddToIndex ( to ) ;
326
266
}
327
267
328
268
UpdatePhysicalIndex ( ) ;
@@ -331,30 +271,16 @@ public void Move(IEnumerable<string> sourcePaths, IEnumerable<string> destinatio
331
271
/// <summary>
332
272
/// Removes a file from the working directory and promotes the removal to the staging area.
333
273
/// </summary>
334
- /// <param name= "path">The relative path within the working directory to the file .</param>
274
+ /// <param name = "path">The path of the file within the working directory .</param>
335
275
public void Remove ( string path )
336
276
{
337
- Ensure . ArgumentNotNullOrEmptyString ( path , "path" ) ;
338
-
339
- string relativePath = BuildRelativePathFrom ( repo , path ) ;
340
-
341
- string wd = repo . Info . WorkingDirectory ;
342
- if ( Directory . Exists ( Path . Combine ( wd , relativePath ) ) )
343
- {
344
- throw new NotImplementedException ( ) ;
345
- }
346
-
347
- RemoveFromIndex ( relativePath ) ;
348
-
349
- File . Delete ( Path . Combine ( wd , relativePath ) ) ;
350
-
351
- UpdatePhysicalIndex ( ) ;
277
+ Remove ( new [ ] { path } ) ;
352
278
}
353
279
354
280
/// <summary>
355
281
/// Removes a collection of files from the working directory and promotes the removal to the staging area.
356
282
/// </summary>
357
- /// <param name= "paths">The relative paths within the working directory to the files .</param>
283
+ /// <param name = "paths">The collection of paths of the files within the working directory .</param>
358
284
public void Remove ( IEnumerable < string > paths )
359
285
{
360
286
Ensure . ArgumentNotNull ( paths , "paths" ) ;
@@ -366,15 +292,17 @@ public void Remove(IEnumerable<string> paths)
366
292
throw new ArgumentNullException ( "paths" ) ;
367
293
}
368
294
369
- string wd = repo . Info . WorkingDirectory ;
370
295
foreach ( KeyValuePair < string , FileStatus > keyValuePair in batch )
371
296
{
372
- if ( Directory . Exists ( Path . Combine ( wd , keyValuePair . Key ) ) )
297
+ if ( ! keyValuePair . Value . HasAny ( new [ ] { FileStatus . Missing , FileStatus . Nonexistent , FileStatus . Removed , FileStatus . Untracked } ) )
373
298
{
374
- throw new NotImplementedException ( ) ;
299
+ continue ;
375
300
}
301
+
302
+ throw new LibGit2Exception ( string . Format ( "Unable to remove file '{0}'. Its current status is '{1}'." , keyValuePair . Key , Enum . GetName ( typeof ( FileStatus ) , keyValuePair . Value ) ) ) ;
376
303
}
377
304
305
+ string wd = repo . Info . WorkingDirectory ;
378
306
foreach ( KeyValuePair < string , FileStatus > keyValuePair in batch )
379
307
{
380
308
RemoveFromIndex ( keyValuePair . Key ) ;
@@ -399,6 +327,42 @@ private IDictionary<string, FileStatus> PrepareBatch(IEnumerable<string> paths)
399
327
return dic ;
400
328
}
401
329
330
+ private IDictionary < Tuple < string , FileStatus > , Tuple < string , FileStatus > > PrepareBatch ( IEnumerable < string > leftPaths , IEnumerable < string > rightPaths )
331
+ {
332
+ IDictionary < Tuple < string , FileStatus > , Tuple < string , FileStatus > > dic = new Dictionary < Tuple < string , FileStatus > , Tuple < string , FileStatus > > ( ) ;
333
+
334
+ IEnumerator < string > leftEnum = leftPaths . GetEnumerator ( ) ;
335
+ IEnumerator < string > rightEnum = rightPaths . GetEnumerator ( ) ;
336
+
337
+ while ( Enumerate ( leftEnum , rightEnum ) )
338
+ {
339
+ Tuple < string , FileStatus > from = BuildFrom ( leftEnum . Current ) ;
340
+ Tuple < string , FileStatus > to = BuildFrom ( rightEnum . Current ) ;
341
+ dic . Add ( from , to ) ;
342
+ }
343
+
344
+ return dic ;
345
+ }
346
+
347
+ private Tuple < string , FileStatus > BuildFrom ( string path )
348
+ {
349
+ string relativePath = BuildRelativePathFrom ( repo , path ) ;
350
+ return new Tuple < string , FileStatus > ( relativePath , RetrieveStatus ( relativePath ) ) ;
351
+ }
352
+
353
+ private bool Enumerate ( IEnumerator < string > leftEnum , IEnumerator < string > rightEnum )
354
+ {
355
+ bool isLeftEoF = leftEnum . MoveNext ( ) ;
356
+ bool isRightEoF = rightEnum . MoveNext ( ) ;
357
+
358
+ if ( isLeftEoF == isRightEoF )
359
+ {
360
+ return isLeftEoF ;
361
+ }
362
+
363
+ throw new ArgumentException ( "The collection of paths are of different lengths." ) ;
364
+ }
365
+
402
366
private void AddToIndex ( string relativePath )
403
367
{
404
368
relativePath = PosixPathHelper . ToPosix ( relativePath ) ;
@@ -477,8 +441,8 @@ private static string BuildRelativePathFrom(Repository repo, string path)
477
441
/// <summary>
478
442
/// Retrieves the state of a file in the working directory, comparing it against the staging area and the latest commmit.
479
443
/// </summary>
480
- /// <param name= "filePath">The relative path within the working directory to the file.</param>
481
- /// <returns>A <see cref= "FileStatus" /> representing the state of the <paramref name= "filePath"/> parameter.</returns>
444
+ /// <param name = "filePath">The relative path within the working directory to the file.</param>
445
+ /// <returns>A <see cref = "FileStatus" /> representing the state of the <paramref name = "filePath" /> parameter.</returns>
482
446
public FileStatus RetrieveStatus ( string filePath )
483
447
{
484
448
Ensure . ArgumentNotNullOrEmptyString ( filePath , "filePath" ) ;
@@ -501,7 +465,7 @@ public FileStatus RetrieveStatus(string filePath)
501
465
/// <summary>
502
466
/// Retrieves the state of all files in the working directory, comparing them against the staging area and the latest commmit.
503
467
/// </summary>
504
- /// <returns>A <see cref= "RepositoryStatus" /> holding the state of all the files.</returns>
468
+ /// <returns>A <see cref = "RepositoryStatus" /> holding the state of all the files.</returns>
505
469
public RepositoryStatus RetrieveStatus ( )
506
470
{
507
471
return new RepositoryStatus ( repo ) ;
0 commit comments