8000 Move Remove to Commands · libgit2/libgit2sharp@2d4d66d · GitHub
[go: up one dir, main page]

Skip to content

Commit 2d4d66d

Browse files
committed
Move Remove to Commands
This deprecates them from the repository itself and makes it clear this isn't a fundamental operation but something which builds on them.
1 parent 7a9d52b commit 2d4d66d

11 files changed

+272
-130
lines changed

LibGit2Sharp.Tests/CheckoutFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public void CheckoutAddsMissingFilesInWorkingDirectory()
156156
// Remove the file in master branch
157157
// Verify it exists after checking out otherBranch.
158158
string fileFullPath = Path.Combine(repo.Info.WorkingDirectory, originalFilePath);
159-
repo.Remove(fileFullPath);
159+
Commands.Remove(repo, fileFullPath);
160160
repo.Commit("2nd commit", Constants.Signature, Constants.Signature);
161161

162162
// Checkout other_branch

LibGit2Sharp.Tests/CommitFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,7 +1039,7 @@ public void CanNotAmendACommitInAWayThatWouldLeadTheNewCommitToBecomeEmpty()
10391039

10401040
repo.Commit("One commit", Constants.Signature, Constants.Signature);
10411041

1042-
repo.Remove("new.txt");
1042+
Commands.Remove(repo, "new.txt");
10431043

10441044
Assert.Throws<EmptyCommitException>(() => repo.Commit("Oops", Constants.Signature, Constants.Signature,
10451045
new CommitOptions { AmendPreviousCommit = true }));

LibGit2Sharp.Tests/ConflictFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public void CanResolveConflictsByRemovingFromTheIndex(
7777
Assert.NotNull(repo.Index.Conflicts[filename]);
7878
Assert.Equal(0, repo.Index.Conflicts.ResolvedConflicts.Count());
7979

80-
repo.Remove(filename, removeFromWorkdir);
80+
Commands.Remove(repo, filename, removeFromWorkdir);
8181

8282
Assert.Null(repo.Index.Conflicts[filename]);
8383
Assert.Equal(count - removedIndexEntries, repo.Index.Count);

LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public void CanDetectABinaryDeletion()
133133
var patch = repo.Diff.Compare<Patch>(commit.Tree, DiffTargets.WorkingDirectory, new [] {filename});
134134
Assert.True(patch[filename].IsBinaryComparison);
135135

136-
repo.Remove(filename);
136+
Commands.Remove(repo, filename);
137137
var commit2 = repo.Commit("Delete binary file", Constants.Signature, Constants.Signature);
138138

139139
var patch2 = repo.Diff.Compare<Patch>(commit.Tree, commit2.Tree, new[] { filename });

LibGit2Sharp.Tests/MergeFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ public void CanMergeIntoOrphanedBranch()
751751
foreach(var entry in repo.RetrieveStatus())
752752
{
753753
Commands.Unstage(repo, entry.FilePath);
754-
repo.Remove(entry.FilePath, true);
754+
Commands.Remove(repo, entry.FilePath, true);
755755
}
756756

757757
// Assert that we have an empty working directory.

LibGit2Sharp.Tests/RemoveFixture.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ public void CanRemoveAnUnalteredFileFromTheIndexWithoutRemovingItFromTheWorkingD
5959

6060
if (throws)
6161
{
62-
Assert.Throws<RemoveFromIndexException>(() => repo.Remove(filename, removeFromWorkdir));
62+
Assert.Throws<RemoveFromIndexException>(() => Commands.Remove(repo, filename, removeFromWorkdir));
6363
Assert.Equal(count, repo.Index.Count);
6464
}
6565
else
6666
{
67-
repo.Remove(filename, removeFromWorkdir);
67+
Commands.Remove(repo, filename, removeFromWorkdir);
6868

6969
Assert.Equal(count - 1, repo.Index.Count);
7070
Assert.Equal(existsAfterRemove, File.Exists(fullpath));
@@ -93,8 +93,8 @@ public void RemovingAModifiedFileWhoseChangesHaveBeenPromotedToTheIndexAndWithAd
9393
File.AppendAllText(fullpath, "additional content");
9494
Assert.Equal(FileStatus.ModifiedInIndex | FileStatus.ModifiedInWorkdir, repo.RetrieveStatus(filename));
9595

96-
Assert.Throws<RemoveFromIndexException>(() => repo.Remove(filename));
97-
Assert.Throws<RemoveFromIndexException>(() => repo.Remove(filename, false));
96+
Assert.Throws<RemoveFromIndexException>(() => Commands.Remove(repo, filename));
97+
Assert.Throws<RemoveFromIndexException>(() => Commands.Remove(repo, filename, false));
9898
}
9999
}
100100

@@ -113,7 +113,7 @@ public void CanRemoveAFolderThroughUsageOfPathspecsForNewlyAddedFiles()
113113
int count = repo.Index.Count;
114114

115115
Assert.True(Directory.Exists(Path.Combine(repo.Info.WorkingDirectory, "2")));
116-
repo.Remove("2", false);
116+
Commands.Remove(repo, "2", false);
117117

118118
Assert.Equal(count - 5, repo.Index.Count);
119119
}
@@ -128,7 +128,7 @@ public void CanRemoveAFolderThroughUsageOfPathspecsForFilesAlreadyInTheIndexAndI
128128
int count = repo.Index.Count;
129129

130130
Assert.True(Directory.Exists(Path.Combine(repo.Info.WorkingDirectory, "1")));
131-
repo.Remove("1");
131+
Commands.Remove(repo, "1");
132132

133133
Assert.False(Directory.Exists(Path.Combine(repo.Info.WorkingDirectory, "1")));
134134
Assert.Equal(count - 1, repo.Index.Count);
@@ -148,8 +148,8 @@ public void RemovingAnUnknownFileWithLaxExplicitPathsValidationDoesntThrow(strin
148148
Assert.Null(repo.Index[relativePath]);
149149
Assert.Equal(status, repo.RetrieveStatus(relativePath));
150150

151-
repo.Remove(relativePath, i % 2 == 0);
152-
repo.Remove(relativePath, i % 2 == 0,
151+
Commands.Remove(repo, relativePath, i % 2 == 0);
152+
Commands.Remove(repo, relativePath, i % 2 == 0,
153153
new ExplicitPathsOptions {ShouldFailOnUnmatchedPath = false});
154154
}
155155
}
@@ -169,7 +169,7 @@ public void RemovingAnUnknownFileThrowsIfExplicitPath(string relativePath, FileS
169169
Assert.Equal(status, repo.RetrieveStatus(relativePath));
170170

171171
Assert.Throws<UnmatchedPathException>(
172-
() => repo.Remove(relativePath, i%2 == 0, new ExplicitPathsOptions()));
172+
() => Commands.Remove(repo, relativePath, i%2 == 0, new ExplicitPathsOptions()));
173173
}
174174
}
175175
}
@@ -180,10 +180,10 @@ public void RemovingFileWithBadParamsThrows()
180180
var path = SandboxStandardTestRepoGitDir();
181181
using (var repo = new Repository(path))
182182
{
183-
Assert.Throws<ArgumentException>(() => repo.Remove(string.Empty));
184-
Assert.Throws<ArgumentNullException>(() => repo.Remove((string)null));
185-
Assert.Throws<ArgumentException>(() => repo.Remove(new string[] { }));
186-
Assert.Throws<ArgumentNullException>(() => repo.Remove(new string[] { null }));
183+
Assert.Throws<ArgumentException>(() => Commands.Remove(repo, string.Empty));
184+
Assert.Throws<ArgumentNullException>(() => Commands.Remove(repo, (string)null));
185+
Assert.Throws<ArgumentException>(() 1CF5 => Commands.Remove(repo, new string[] { }));
186+
Assert.Throws<ArgumentNullException>(() => Commands.Remove(repo, new string[] { null }));
187187
}
188188
}
189189
}

LibGit2Sharp/Commands/Remove.cs

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
using System.Linq;
2+
using System.IO;
3+
using System.Collections.Generic;
4+
using LibGit2Sharp;
5+
using LibGit2Sharp.Core;
6+
7+
namespace LibGit2Sharp
8+
{
9+
public static partial class Commands
10+
{
11+
12+
/// <summary>
13+
/// Removes a file from the staging area, and optionally removes it from the working directory as well.
14+
/// <para>
15+
/// If the file has already been deleted from the working directory, this method will only deal
16+
/// with promoting the removal to the staging area.
17+
/// </para>
18+
/// <para>
19+
/// The default behavior is to remove the file from the working directory as well.
20+
/// </para>
21+
/// </summary>
22+
/// <param name="repository">The <see cref="IRepository"/> being worked with.</param>
23+
/// <param name="path">The path of the file within the working directory.</param>
24+
public static void Remove(IRepository repository, string path)
25+
{
26+
Remove(repository, path, true, null);
27+
}
28+
29+
/// <summary>
30+
/// Removes a file from the staging area, and optionally removes it from the working directory as well.
31+
/// <para>
32+
/// If the file has already been deleted from the working directory, this method will only deal
33+
/// with promoting the removal to the staging area.
34+
/// </para>
35+
/// <para>
36+
/// The default behavior is to remove the file from the working directory as well.
37+
/// </para>
38+
/// </summary>
39+
/// <param name="repository">The <see cref="IRepository"/> being worked with.</param>
40+
/// <param name="path">The path of the file within the working directory.</param>
41+
/// <param name="removeFromWorkingDirectory">True to remove the file from the working directory, False otherwise.</param>
42+
public static void Remove(IRepository repository, string path, bool removeFromWorkingDirectory)
43+
{
44+
Remove(repository, path, removeFromWorkingDirectory, null);
45+
}
46+
47+
48+
/// <summary>
49+
/// Removes a file from the staging area, and optionally removes it from the working directory as well.
50+
/// <para>
51+
/// If the file has already been deleted from the working directory, this method will only deal
52+
/// with promoting the removal to the staging area.
53+
/// </para>
54+
/// <para>
55+
/// The default behavior is to remove the file from the working directory as well.
56+
/// </para>
57+
/// <para>
58+
/// When not passing a <paramref name="explicitPathsOptions"/>, the passed path will be treated as
59+
/// a pathspec. You can for example use it to pass the relative path to a folder inside the working directory,
60+
/// so that all files beneath this folders, and the folder itself, will be removed.
61+
/// </para>
62+
/// </summary>
63+
/// <param name="repository">The repository in which to operate</param>
64+
/// <param name="path">The path of the file within the working directory.</param>
65+
/// <param name="removeFromWorkingDirectory">True to remove the file from the working directory, False otherwise.</param>
66+
/// <param name="explicitPathsOptions">
67+
/// The passed <paramref name="path"/> will be treated as an explicit path.
68+
/// Use these options to determine how unmatched explicit paths should be handled.
69+
/// </param>
70+
public static void Remove(IRepository repository, string path, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions)
71+
{
72+
Ensure.ArgumentNotNull(repository, "repository");
73+
Ensure.ArgumentNotNull(path, "path");
74+
75+
Remove(repository, new[] { path }, removeFromWorkingDirectory, explicitPathsOptions);
76+
}
77+
78+
/// <summary>
79+
/// Removes a collection of fileS from the staging, and optionally removes them from the working directory as well.
80+
/// <para>
81+
/// If a file has already been deleted from the working directory, this method will only deal
82+
/// with promoting the removal to the staging area.
83+
/// </para>
84+
/// <para>
85+
/// The default behavior is to remove the files from the working directory as well.
86+
/// </para>
87+
/// </summary>
88+
/// <param name="repository">The <see cref="IRepository"/> being worked with.</param>
89+
/// <param name="paths">The collection of paths of the files within the working directory.</param>
90+
public static void Remove(IRepository repository, IEnumerable<string> paths)
91+
{
92+
Remove(repository, paths, true, null);
93+
}
94+
95+
/// <summary>
96+
/// Removes a collection of fileS from the staging, and optionally removes them from the working directory as well.
97+
/// <para>
98+
/// If a file has already been deleted from the working directory, this method will only deal
99+
/// with promoting the removal to the staging area.
100+
/// </para>
101+
/// <para>
102+
/// The default behavior is to remove the files from the working directory as well.
103+
/// </para>
104+
/// <para>
105+
/// When not passing a <paramref name="explicitPathsOptions"/>, the passed paths will be treated as
106+
/// a pathspec. You can for example use it to pass the relative paths to folders inside the working directory,
107+
/// so that all files beneath these folders, and the folders themselves, will be removed.
108+
/// </para>
109+
/// </summary>
110+
/// <param name="repository">The repository in which to operate</param>
111+
/// <param name="paths">The collection of paths of the files within the working directory.</param>
112+
/// <param name="removeFromWorkingDirectory">True to remove the files from the working directory, False otherwise.</param>
113+
/// <param name="explicitPathsOptions">
114+
/// The passed <paramref name="paths"/> will be treated as explicit paths.
115+
/// Use these options to determine how unmatched explicit paths should be handled.
116+
/// </param>
117+
public static void Remove(IRepository repository, IEnumerable<string> paths, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions)
118+
{
119+
Ensure.ArgumentNotNull(repository, "repository");
120+
Ensure.ArgumentNotNullOrEmptyEnumerable<string>(paths, "paths");
121+
122+
var pathsToDelete = paths.Where(p => Directory.Exists(Path.Combine(repository.Info.WorkingDirectory, p))).ToList();
123+
var notConflictedPaths = new List<string>();
124+
var index = repository.Index;
125+
126+
foreach (var path in paths)
127+
{
128+
Ensure.ArgumentNotNullOrEmptyString(path, "path");
129+
130+
var conflict = index.Conflicts[path];
131+
132+
if (conflict != null)
133+
{
134+
index.Remove(path);
135+
pathsToDelete.Add(path);
136+
}
137+
else
138+
{
139+
notConflictedPaths.Add(path);
140+
}
141+
}
142+
143+
// Make sure status will see the changes from before this
144+
index.Write();
145+
146+
if (notConflictedPaths.Count > 0)
147+
{
148+
pathsToDelete.AddRange(RemoveStagedItems(repository, notConflictedPaths, removeFromWorkingDirectory, explicitPathsOptions));
149+
}
150+
151+
if (removeFromWorkingDirectory)
152+
{
153+
RemoveFilesAndFolders(repository, pathsToDelete);
154+
}
155+
156+
index.Write();
157+
}
158+
159+
private static void RemoveFilesAndFolders(IRepository repository, IEnumerable<string> pathsList)
160+
{
161+
string wd = repository.Info.WorkingDirectory;
162+
163+
foreach (string path in pathsList)
164+
{
165+
string fileName = Path.Combine(wd, path);
166+
167+
if (Directory.Exists(fileName))
168+
{
169+
Directory.Delete(fileName, true);
170+
continue;
171+
}
172+
173+
if (!File.Exists(fileName))
174+
{
175+
continue;
176+
}
177+
178+
File.Delete(fileName);
179+
}
180+
}
181+
182+
private static IEnumerable<string> RemoveStagedItems(IRepository repository, IEnumerable<string> paths, bool removeFromWorkingDirectory = true, ExplicitPathsOptions explicitPathsOptions = null)
183+
{
184+
var removed = new List<string>();
185+
var changes = repository.Diff.Compare<TreeChanges>(DiffModifiers.IncludeUnmodified | DiffModifiers.IncludeUntracked, paths, explicitPathsOptions);
186+
var index = repository.Index;
187+
188+
foreach (var treeEntryChanges in changes)
189+
{
190+
var status = repository.RetrieveStatus(treeEntryChanges.Path);
191+
192+
switch (treeEntryChanges.Status)
193+
{
194+
case ChangeKind.Added:
195+
case ChangeKind.Deleted:
196+
removed.Add(treeEntryChanges.Path);
197+
index.Remove(treeEntryChanges.Path);
198+
break;
199+
200+
case ChangeKind.Unmodified:
201+
if (removeFromWorkingDirectory && (
202+
status.HasFlag(FileStatus.ModifiedInIndex) ||
203+
status.HasFlag(FileStatus.NewInIndex)))
204+
{
205+
throw new RemoveFromIndexException("Unable to remove file '{0}', as it has changes staged in the index. You can call the Remove() method with removeFromWorkingDirectory=false if you want to remove it from the index only.",
206+
treeEntryChanges.Path);
207+
}
208+
removed.Add(treeEntryChanges.Path);
209+
index.Remove(treeEntryChanges.Path);
210+
continue;
211+
212+
case ChangeKind.Modified:
213+
if (status.HasFlag(FileStatus.ModifiedInWorkdir) && status.HasFlag(FileStatus.ModifiedInIndex))
214+
{
215+
throw new RemoveFromIndexException("Unable to remove file '{0}', as it has staged content different from both the working directory and the HEAD.",
216+
treeEntryChanges.Path);
217+
}
218+
if (removeFromWorkingDirectory)
219+
{
220+
throw new RemoveFromIndexException("Unable to remove file '{0}', as it has local modifications. You can call the Remove() method with removeFromWorkingDirectory=false if you want to remove it from the index only.",
221+
treeEntryChanges.Path);
222+
}
223+
removed.Add(treeEntryChanges.Path);
224+
index.Remove(treeEntryChanges.Path);
225+
continue;
226+
227+
default:
228+
throw new RemoveFromIndexException("Unable to remove file '{0}'. Its current status is '{1}'.",
229+
treeEntryChanges.Path,
230+
treeEntryChanges.Status);
231+
}
232+
}
233+
234+
index.Write();
235+
236+
return removed;
237+
}
238+
}
239+
}
240+

LibGit2Sharp/IRepository.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ public interface IRepository : IDisposable
341341
/// The passed <paramref name="path"/> will be treated as an explicit path.
342342
/// Use these options to determine how unmatched explicit paths should be handled.
343343
/// </param>
344+
[Obsolete("This method is deprecated. Please use LibGit2Sharp.Commands.Remove()")]
344345
void Remove(string path, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions);
345346

346347
/// <summary>
@@ -364,6 +365,7 @@ public interface IRepository : IDisposable
364365
/// The passed <paramref name="paths"/> will be treated as explicit paths.
365366
/// Use these options to determine how unmatched explicit paths should be handled.
366367
/// </param>
368+
[Obsolete("This method is deprecated. Please use LibGit2Sharp.Commands.Unstage()")]
367369
void Remove(IEnumerable<string> paths, bool removeFromWorkingDirectory, ExplicitPathsOptions explicitPathsOptions);
368370

369371
/// <summary>

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@
353353
<Compile Include="Commands\Pull.cs" />
354354
<Compile Include="Commands\Fetch.cs" />
355355
<Compile Include="Commands\Stage.cs" />
356+
<Compile Include="Commands\Remove.cs" />
356357
</ItemGroup>
357358
<ItemGroup>
358359
<CodeAnalysisDictionary Include="CustomDictionary.xml" />

0 commit comments

Comments
 (0)
0