Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 84154d6

Browse files
committed
Merge pull request libgit2#1281 from libgit2/lazy-diff-results
Lazy TreeChanges, move ownership of diff handle for diff results
2 parents 63771c5 + 53b267b commit 84154d6

15 files changed

+784
-566
lines changed

LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs

Lines changed: 185 additions & 151 deletions
Large diffs are not rendered by default.

LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs

Lines changed: 247 additions & 201 deletions
Large diffs are not rendered by default.

LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,12 @@ public void CanCompareTheWorkDirAgainstTheIndex()
3333
var path = SandboxStandardTestRepoGitDir();
3434
using (var repo = new Repository(path))
3535
{
36-
var changes = repo.Diff.Compare<TreeChanges>();
37-
38-
Assert.Equal(2, changes.Count());
39-
Assert.Equal("deleted_unstaged_file.txt", changes.Deleted.Single().Path);
40-
Assert.Equal("modified_unstaged_file.txt", changes.Modified.Single().Path);
36+
using (var changes = repo.Diff.Compare<TreeChanges>())
37+
{
38+
Assert.Equal(2, changes.Count());
39+
Assert.Equal("deleted_unstaged_file.txt", changes.Deleted.Single().Path);
40+
Assert.Equal("modified_unstaged_file.txt", changes.Modified.Single().Path);
41+
}
4142
}
4243
}
4344

@@ -51,11 +52,15 @@ public void CanCompareTheWorkDirAgainstTheIndexWithLaxUnmatchedExplicitPathsVali
5152
{
5253
Assert.Equal(currentStatus, repo.RetrieveStatus(relativePath));
5354

54-
var changes = repo.Diff.Compare<TreeChanges>(new[] { relativePath }, false, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false });
55-
Assert.Equal(0, changes.Count());
55+
using (var changes = repo.Diff.Compare<TreeChanges>(new[] { relativePath }, false, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false }))
56+
{
57+
Assert.Equal(0, changes.Count());
58+
}
5659

57-
changes = repo.Diff.Compare<TreeChanges>(new[] { relativePath });
58-
Assert.Equal(0, changes.Count());
60+
using (var changes = repo.Diff.Compare<TreeChanges>(new[] { relativePath }))
61+
{
62+
Assert.Equal(0, changes.Count());
63+
}
5964
}
6065
}
6166

@@ -85,12 +90,14 @@ public void CallbackForUnmatchedExplicitPathsIsCalledWhenSet(string relativePath
8590
{
8691
Assert.Equal(currentStatus, repo.RetrieveStatus(relativePath));
8792

88-
repo.Diff.Compare<TreeChanges>(new[] { relativePath }, false, new ExplicitPathsOptions
93+
using (var changes = repo.Diff.Compare<TreeChanges>(new[] { relativePath }, false, new ExplicitPathsOptions
8994
{
9095
ShouldFailOnUnmatchedPath = false,
91-
OnUnmatchedPath = callback.OnUnmatchedPath });
92-
93-
Assert.True(callback.WasCalled);
96+
OnUnmatchedPath = callback.OnUnmatchedPath
97+
}))
98+
{
99+
Assert.True(callback.WasCalled);
100+
}
94101
}
95102
}
96103

@@ -130,21 +137,23 @@ public void ComparingReliesOnProvidedConfigEntriesIfAny()
130137
using (var repo = new Repository(path))
131138
{
132139
SetFilemode(repo, true);
133-
var changes = repo.Diff.Compare<TreeChanges>(new[] { file });
134-
135-
Assert.Equal(1, changes.Count());
140+
using(var changes = repo.Diff.Compare<TreeChanges>(new[] { file }))
141+
{
142+
Assert.Equal(1, changes.Count());
136143

137-
var change = changes.Modified.Single();
138-
Assert.Equal(Mode.ExecutableFile, change.OldMode);
139-
Assert.Equal(Mode.NonExecutableFile, change.Mode);
144+
var change = changes.Modified.Single();
145+
Assert.Equal(Mode.ExecutableFile, change.OldMode);
146+
Assert.Equal(Mode.NonExecutableFile, change.Mode);
147+
}
140148
}
141149

142150
using (var repo = new Repository(path))
143151
{
144152
SetFilemode(repo, false);
145-
var changes = repo.Diff.Compare<TreeChanges>(new[] { file });
146-
147-
Assert.Equal(0, changes.Count());
153+
using(var changes = repo.Diff.Compare<TreeChanges>(new[] { file }))
154+
{
155+
Assert.Equal(0, changes.Count());
156+
}
148157
}
149158
}
150159

@@ -159,12 +168,13 @@ public void CanCompareTheWorkDirAgainstTheIndexWithUntrackedFiles()
159168
var path = SandboxStandardTestRepoGitDir();
160169
using (var repo = new Repository(path))
161170
{
162-
var changes = repo.Diff.Compare<TreeChanges>(null, true);
163-
164-
Assert.Equal(3, changes.Count());
165-
Assert.Equal("deleted_unstaged_file.txt", changes.Deleted.Single().Path);
166-
Assert.Equal("modified_unstaged_file.txt", changes.Modified.Single().Path);
167-
Assert.Equal("new_untracked_file.txt", changes.Added.Single().Path);
171+
using (var changes = repo.Diff.Compare<TreeChanges>(null, true))
172+
{
173+
Assert.Equal(3, changes.Count());
174+
Assert.Equal("deleted_unstaged_file.txt", changes.Deleted.Single().Path);
175+
Assert.Equal("modified_unstaged_file.txt", changes.Modified.Single().Path);
176+
Assert.Equal("new_untracked_file.txt", changes.Added.Single().Path);
177+
}
168178
}
169179
}
170180
}

LibGit2Sharp.Tests/PatchStatsFixture.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ public void CanExtractStatisticsFromDiff()
1313
{
1414
var oldTree = repo.Lookup<Commit>("origin/packed-test").Tree;
1515
var newTree = repo.Lookup<Commit>("HEAD").Tree;
16-
var stats = repo.Diff.Compare<PatchStats>(oldTree, newTree);
16+
using (var stats = repo.Diff.Compare<PatchStats>(oldTree, newTree))
17+
{
18+
Assert.Equal(8, stats.TotalLinesAdded);
19+
Assert.Equal(1, stats.TotalLinesDeleted);
1720

18-
Assert.Equal(8, stats.TotalLinesAdded);
19-
Assert.Equal(1, stats.TotalLinesDeleted);
20-
21-
var contentStats = stats["new.txt"];
22-
Assert.Equal(1, contentStats.LinesAdded);
23-
Assert.Equal(1, contentStats.LinesDeleted);
21+
var contentStats = stats["new.txt"];
22+
Assert.Equal(1, contentStats.LinesAdded);
23+
Assert.Equal(1, contentStats.LinesDeleted);
24+
}
2425
}
2526
}
2627
}

LibGit2Sharp/Commands/Remove.cs

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -182,58 +182,60 @@ private static void RemoveFilesAndFolders(IRepository repository, IEnumerable<st
182182
private static IEnumerable<string> RemoveStagedItems(IRepository repository, IEnumerable<string> paths, bool removeFromWorkingDirectory = true, ExplicitPathsOptions explicitPathsOptions = null)
183183
{
184184
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)
185+
using (var changes = repository.Diff.Compare<TreeChanges>(DiffModifiers.IncludeUnmodified | DiffModifiers.IncludeUntracked, paths, explicitPathsOptions))
189186
{
190-
var status = repository.RetrieveStatus(treeEntryChanges.Path);
187+
var index = repository.Index;
191188

192-
switch (treeEntryChanges.Status)
189+
foreach (var treeEntryChanges in changes)
193190
{
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);
191+
var status = repository.RetrieveStatus(treeEntryChanges.Path);
192+
193+
switch (treeEntryChanges.Status)
194+
{
195+
case ChangeKind.Added:
196+
case ChangeKind.Deleted:
197+
removed.Add(treeEntryChanges.Path);
198+
index.Remove(treeEntryChanges.Path);
199+
break;
200+
201+
case ChangeKind.Unmodified:
202+
if (removeFromWorkingDirectory && (
203+
status.HasFlag(FileStatus.ModifiedInIndex) ||
204+
status.HasFlag(FileStatus.NewInIndex)))
205+
{
206+
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.",
207+
treeEntryChanges.Path);
208+
}
209+
removed.Add(treeEntryChanges.Path);
210+
index.Remove(treeEntryChanges.Path);
211+
continue;
212+
213+
case ChangeKind.Modified:
214+
if (status.HasFlag(FileStatus.ModifiedInWorkdir) && status.HasFlag(FileStatus.ModifiedInIndex))
215+
{
216+
throw new RemoveFromIndexException("Unable to remove file '{0}', as it has staged content different from both the working directory and the HEAD.",
217+
treeEntryChanges.Path);
218+
}
219+
if (removeFromWorkingDirectory)
220+
{
221+
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.",
222+
treeEntryChanges.Path);
223+
}
224+
removed.Add(treeEntryChanges.Path);
225+
index.Remove(treeEntryChanges.Path);
226+
continue;
227+
228+
default:
229+
throw new RemoveFromIndexException("Unable to remove file '{0}'. Its current status is '{1}'.",
230+
treeEntryChanges.Path,
231+
treeEntryChanges.Status);
232+
}
231233
}
232-
}
233234

234-
index.Write();
235+
index.Write();
235236

236-
return removed;
237+
return removed;
238+
}
237239
}
238240
}
239241
}

LibGit2Sharp/Commands/Stage.cs

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -74,68 +74,69 @@ public static void Stage(IRepository repository, IEnumerable<string> paths, Stag
7474
diffModifiers |= DiffModifiers.IncludeIgnored;
7575
}
7676

77-
var changes = repository.Diff.Compare<TreeChanges>(diffModifiers, paths, explicitPathsOptions,
78-
new CompareOptions { Similarity = SimilarityOptions.None });
79-
80-
var unexpectedTypesOfChanges = changes
81-
.Where(
82-
tec => tec.Status != ChangeKind.Added &&
83-
tec.Status != ChangeKind.Modified &&
84-
tec.Status != ChangeKind.Conflicted &&
85-
tec.Status != ChangeKind.Unmodified &&
86-
tec.Status != ChangeKind.Deleted).ToList();
87-
88-
if (unexpectedTypesOfChanges.Count > 0)
77+
using (var changes = repository.Diff.Compare<TreeChanges>(diffModifiers, paths, explicitPathsOptions,
78+
new CompareOptions { Similarity = SimilarityOptions.None }))
8979
{
90-
throw new InvalidOperationException(
91-
string.Format(CultureInfo.InvariantCulture,
92-
"Entry '{0}' bears an unexpected ChangeKind '{1}'",
93-
unexpectedTypesOfChanges[0].Path, unexpectedTypesOfChanges[0].Status));
94-
}
80+
var unexpectedTypesOfChanges = changes
81+
.Where(
82+
tec => tec.Status != ChangeKind.Added &&
83+
tec.Status != ChangeKind.Modified &&
84+
tec.Status != ChangeKind.Conflicted &&
85+
tec.Status != ChangeKind.Unmodified &&
86+
tec.Status != ChangeKind.Deleted).ToList();
87+
88+
if (unexpectedTypesOfChanges.Count > 0)
89+
{
90+
throw new InvalidOperationException(
91+
string.Format(CultureInfo.InvariantCulture,
92+
"Entry '{0}' bears an unexpected ChangeKind '{1}'",
93+
unexpectedTypesOfChanges[0].Path, unexpectedTypesOfChanges[0].Status));
94+
}
9595

96-
/* Remove files from the index that don't exist on disk */
97-
foreach (TreeEntryChanges treeEntryChanges in changes)
98-
{
99-
switch (treeEntryChanges.Status)
96+
/* Remove files from the index that don't exist on disk */
97+
foreach (TreeEntryChanges treeEntryChanges in changes)
10098
{
101-
case ChangeKind.Conflicted:
102-
if (!treeEntryChanges.Exists)
103-
{
99+
switch (treeEntryChanges.Status)
100+
{
101+
case ChangeKind.Conflicted:
102+
if (!treeEntryChanges.Exists)
103+
{
104+
repository.Index.Remove(treeEntryChanges.Path);
105+
}
106+
break;
107+
108+
case ChangeKind.Deleted:
104109
repository.Index.Remove(treeEntryChanges.Path);
105-
}
106-
break;
107-
108-
case ChangeKind.Deleted:
109-
repository.Index.Remove(treeEntryChanges.Path);
110-
break;
110+
break;
111111

112-
default:
113-
continue;
112+
default:
113+
continue;
114+
}
114115
}
115-
}
116116

117-
foreach (TreeEntryChanges treeEntryChanges in changes)
118-
{
119-
switch (treeEntryChanges.Status)
117+
foreach (TreeEntryChanges treeEntryChanges in changes)
120118
{
121-
case ChangeKind.Added:
122-
case ChangeKind.Modified:
123-
repository.Index.Add(treeEntryChanges.Path);
124-
break;
125-
126-
case ChangeKind.Conflicted:
127-
if (treeEntryChanges.Exists)
128-
{
119+
switch (treeEntryChanges.Status)
120+
{
121+
case ChangeKind.Added:
122+
case ChangeKind.Modified:
129123
repository.Index.Add(treeEntryChanges.Path);
130-
}
131-
break;
132-
133-
default:
134-
continue;
124+
break;
125+
126+
case ChangeKind.Conflicted:
127+
if (treeEntryChanges.Exists)
128+
{
129+
repository.Index.Add(treeEntryChanges.Path);
130+
}
131+
break;
132+
133+
default:
134+
continue;
135+
}
135136
}
136-
}
137137

138-
repository.Index.Write();
138+
repository.Index.Write();
139+
}
139140
}
140141

141142
/// <summary>
@@ -191,9 +192,8 @@ public static void Unstage(IRepository repository, IEnumerable<string> paths, Ex
191192

192193
if (repository.Info.IsHeadUnborn)
193194
{
194-
var changes = repository.Diff.Compare<TreeChanges>(null, DiffTargets.Index, paths, explicitPathsOptions, new CompareOptions { Similarity = SimilarityOptions.None });
195-
196-
repository.Index.Replace(changes);
195+
using (var changes = repository.Diff.Compare<TreeChanges>(null, DiffTargets.Index, paths, explicitPathsOptions, new CompareOptions { Similarity = SimilarityOptions.None }))
196+
repository.Index.Replace(changes);
197197
}
198198
else
199199
{

LibGit2Sharp/Core/FileHistory.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,13 @@ private static void DetermineParentPaths(IRepository repo, Commit currentCommit,
163163

164164
private static string ParentPath(IRepository repo, Commit currentCommit, string currentPath, Commit parentCommit)
165165
{
166-
var treeChanges = repo.Diff.Compare<TreeChanges>(parentCommit.Tree, currentCommit.Tree);
167-
var treeEntryChanges = treeChanges.FirstOrDefault(c => c.Path == currentPath);
168-
return treeEntryChanges != null && treeEntryChanges.Status == ChangeKind.Renamed
169-
? treeEntryChanges.OldPath
170-
: currentPath;
166+
using (var treeChanges = repo.Diff.Compare<TreeChanges>(parentCommit.Tree, currentCommit.Tree))
167+
{
168+
var treeEntryChanges = treeChanges.FirstOrDefault(c => c.Path == currentPath);
169+
return treeEntryChanges != null && treeEntryChanges.Status == ChangeKind.Renamed
170+
? treeEntryChanges.OldPath
171+
: currentPath;
172+
}
171173
}
172174
}
173175
}

0 commit comments

Comments
 (0)