8000 Merge pull request #1180 from libgit2/typesafe-compare · github/libgit2sharp@e734df5 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on Feb 3, 2023. It is now read-only.

Commit e734df5

Browse files
committed
Merge pull request libgit2#1180 from libgit2/typesafe-compare
Initial change to type-safe Diff.Compare
2 parents b279955 + 8a673bb commit e734df5

File tree

8 files changed

+58
-69
lines changed

8 files changed

+58
-69
lines changed

LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,17 +1123,6 @@ public void RetrievingDiffChangesMustAlwaysBeCaseSensitive()
11231123
}
11241124
}
11251125

1126-
[Fact]
1127-
public void CallingCompareWithAnUnsupportedGenericParamThrows()
1128-
{
1129-
var path = SandboxStandardTestRepoGitDir();
1130-
using (var repo = new Repository(path))
1131-
{
1132-
Assert.Throws<LibGit2SharpException>(() => repo.Diff.Compare<string>(default(Tree), default(Tree)));
1133-
Assert.Throws<LibGit2SharpException>(() => repo.Diff.Compare<string>());
1134-
}
1135-
}
1136-
11371126
[Fact]
11381127
public void UsingPatienceAlgorithmCompareOptionProducesPatienceDiff()
11391128
{

LibGit2Sharp.Tests/MetaFixture.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class MetaFixture
1717
{
1818
private static readonly HashSet<Type> explicitOnlyInterfaces = new HashSet<Type>
1919
{
20-
typeof(IBelongToARepository),
20+
typeof(IBelongToARepository), typeof(IDiffResult),
2121
};
2222

2323
[Fact]
@@ -401,6 +401,20 @@ where method.IsDefined(typeof(ExtensionAttribute), false)
401401
select method;
402402
return query;
403403
}
404+
405+
[Fact]
406+
public void AllIDiffResultsAreInChangesBuilder()
407+
{
408+
var diff = typeof(Diff).GetField("ChangesBuilders", BindingFlags.NonPublic | BindingFlags.Static);
409+
var changesBuilders = (System.Collections.IDictionary)diff.GetValue(null);
410+
411+
IEnumerable<Type> diffResults = typeof(Diff).Assembly.GetExportedTypes()
412+
.Where(type => type.GetInterface("IDiffResult") != null);
413+
414+
var nonBuilderTypes = diffResults.Where(diffResult => !changesBuilders.Contains(diffResult));
415+
Assert.False(nonBuilderTypes.Any(), "Classes which implement IDiffResult but are not registered under ChangesBuilders in Diff:" + Environment.NewLine +
416+
string.Join(Environment.NewLine, nonBuilderTypes.Select(type => type.FullName)));
417+
}
404418
}
405419

406420
internal static class TypeExtensions

LibGit2Sharp/Diff.cs

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@ private static IDictionary<DiffTargets, Func<Repository, TreeComparisonHandleRet
102102
{ typeof(PatchStats), diff => new PatchStats(diff) },
103103
};
104104

105+
106+
private static T BuildDiffResult<T>(DiffSafeHandle diff) where T : class, IDiffResult
107+
{
108+
Func<DiffSafeHandle, object> builder;
109+
110+
if (!ChangesBuilders.TryGetValue(typeof(T), out builder))
111+
{
112+
throw new LibGit2SharpException(CultureInfo.InvariantCulture,
113+
"User-defined types passed to Compare are not supported. Supported values are: {0}",
114+
string.Join(", ", ChangesBuilders.Keys.Select(x => x.Name)));
115+
}
116+
117+
return (T)builder(diff);
118+
}
119+
105120
/// <summary>
106121
/// Show changes between two <see cref="Blob"/>s.
107122
/// </summary>
@@ -134,7 +149,7 @@ public virtual ContentChanges Compare(Blob oldBlob, Blob newBlob, CompareOptions
134149
/// <param name="oldTree">The <see cref="Tree"/> you want to compare from.</param>
135150
/// <param name="newTree">The <see cref="Tree"/> you want to compare to.</param>
136151
/// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns>
137-
public virtual T Compare<T>(Tree oldTree, Tree newTree) where T : class
152+
public virtual T Compare<T>(Tree oldTree, Tree newTree) where T : class, IDiffResult
138153
{
139154
return Compare<T>(oldTree, newTree, null, null, null);
140155
}
@@ -146,7 +161,7 @@ public virtual T Compare<T>(Tree oldTree, Tree newTree) where T : class
146161
/// <param name="newTree">The <see cref="Tree"/> you want to compare to.</param>
147162
/// <param name="paths">The list of paths (either files or directories) that should be compared.</param>
148163
/// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns>
149-
public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> paths) where T : class
164+
public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> paths) where T : class, IDiffResult
150165
{
151166
return Compare<T>(oldTree, newTree, paths, null, null);
152167
}
@@ -163,7 +178,7 @@ public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> path
163178
/// </param>
164179
/// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns>
165180
public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> paths,
166-
ExplicitPathsOptions explicitPathsOptions) where T : class
181+
ExplicitPathsOptions explicitPathsOptions) where T : class, IDiffResult
167182
{
168183
return Compare<T>(oldTree, newTree, paths, explicitPathsOptions, null);
169184
}
@@ -176,7 +191,7 @@ public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> path
176191
/// <param name="paths">The list of paths (either files or directories) that should be compared.</param>
177192
/// <param name="compareOptions">Additional options to define patch generation behavior.</param>
178193
/// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns>
179-
public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> paths, CompareOptions compareOptions) where T : class
194+
public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> paths, CompareOptions compareOptions) where T : class, IDiffResult
180195
{
181196
return Compare<T>(oldTree, newTree, paths, null, compareOptions);
182197
}
@@ -188,7 +203,7 @@ public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> path
188203
/// <param name="newTree">The <see cref="Tree"/> you want to compare to.</param>
189204
/// <param name="compareOptions">Additional options to define patch generation behavior.</param>
190205
/// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns>
191-
public virtual T Compare<T>(Tree oldTree, Tree newTree, CompareOptions compareOptions) where T : class
206+
public virtual T Compare<T>(Tree oldTree, Tree newTree, CompareOptions compareOptions) where T : class, IDiffResult
192207
{
193208
return Compare<T>(oldTree, newTree, null, null, compareOptions);
194209
}
@@ -206,19 +221,8 @@ public virtual T Compare<T>(Tree oldTree, Tree newTree, CompareOptions compareOp
206221
/// <param name="compareOptions">Additional options to define patch generation behavior.</param>
207222
/// <returns>A <see cref="TreeChanges"/> containing the changes between the <paramref name="oldTree"/> and the <paramref name="newTree"/>.</returns>
208223
public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> paths, ExplicitPathsOptions explicitPathsOptions,
209-
CompareOptions compareOptions) where T : class
224+
CompareOptions compareOptions) where T : class, IDiffResult
210225
{
211-
Func<DiffSafeHandle, object> builder;
212-
213-
if (!ChangesBuilders.TryGetValue(typeof(T), out builder))
214-
{
215-
throw new LibGit2SharpException(CultureInfo.InvariantCulture,
216-
"Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.",
217-
typeof(T),
218-
typeof(TreeChanges),
219-
typeof(Patch));
220-
}
221-
222226
var comparer = TreeToTree(repo);
223227
ObjectId oldTreeId = oldTree != null ? oldTree.Id : null;
224228
ObjectId newTreeId = newTree != null ? newTree.Id : null;
@@ -236,7 +240,7 @@ public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> path
236240

237241
using (DiffSafeHandle diff = BuildDiffList(oldTreeId, newTreeId, comparer, diffOptions, paths, explicitPathsOptions, compareOptions))
238242
{
239-
return (T)builder(diff);
243+
return BuildDiffResult<T>(diff);
240244
}
241245
}
242246

@@ -252,7 +256,7 @@ public virtual T Compare<T>(Tree oldTree, Tree newTree, IEnumerable<string> path
252256
/// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or
253257
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
254258
/// <returns>A <typeparamref name="T"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns>
255-
public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets) where T : class
259+
public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets) where T : class, IDiffResult
256260
{
257261
return Compare<T>(oldTree, diffTargets, null, null, null);
258262
}
@@ -270,7 +274,7 @@ public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets) where T : cla
270274
/// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or
271275
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
272276
/// <returns>A <typeparamref name="T"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns>
273-
public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<string> paths) where T : class
277+
public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<string> paths) where T : class, IDiffResult
274278
{
275279
return Compare<T>(oldTree, diffTargets, paths, null, null);
276280
}
@@ -293,7 +297,7 @@ public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<s
293297
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
294298
/// <returns>A <typeparamref name="T"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns>
295299
public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<string> paths,
296-
ExplicitPathsOptions explicitPathsOptions) where T : class
300+
ExplicitPathsOptions explicitPathsOptions) where T : class, IDiffResult
297301
{
298302
return Compare<T>(oldTree, diffTargets, paths, explicitPathsOptions, null);
299303
}
@@ -317,19 +321,8 @@ public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<s
317321
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
318322
/// <returns>A <typeparamref name="T"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns>
319323
public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<string> paths,
320-
ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) where T : class
324+
ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) where T : class, IDiffResult
321325
{
322-
Func<DiffSafeHandle, object> builder;
323-
324-
if (!ChangesBuilders.TryGetValue(typeof(T), out builder))
325-
{
326-
throw new LibGit2SharpException(CultureInfo.InvariantCulture,
327-
"Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.",
328-
typeof(T),
329-
typeof(TreeChanges),
330-
typeof(Patch));
331-
}
332-
333326
var comparer = HandleRetrieverDispatcher[diffTargets](repo);
334327
ObjectId oldTreeId = oldTree != null ? oldTree.Id : null;
335328

@@ -349,7 +342,7 @@ public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<s
349342

350343
using (DiffSafeHandle diff = BuildDiffList(oldTreeId, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions))
351344
{
352-
return (T)builder(diff);
345+
return BuildDiffResult<T>(diff);
353346
}
354347
}
355348

@@ -363,7 +356,7 @@ public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<s
363356
/// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or
364357
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
365358
/// <returns>A <typeparamref name="T"/> containing the changes between the working directory and the index.</returns>
366-
public virtual T Compare<T>() where T : class
359+
public virtual T Compare<T>() where T : class, IDiffResult
367360
{
368361
return Compare<T>(DiffModifiers.None);
369362
}
@@ -379,7 +372,7 @@ public virtual T Compare<T>() where T : class
379372
/// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or
380373
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
381374
/// <returns>A <typeparamref name="T"/> containing the changes between the working directory and the index.</returns>
382-
public virtual T Compare<T>(IEnumerable<string> paths) where T : class
375+
public virtual T Compare<T>(IEnumerable<string> paths) where T : class, IDiffResult
383376
{
384377
return Compare<T>(DiffModifiers.None, paths);
385378
}
@@ -396,7 +389,7 @@ public virtual T Compare<T>(IEnumerable<string> paths) where T : class
396389
/// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or
397390
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
398391
/// <returns>A <typeparamref name="T"/> containing the changes between the working directory and the index.</returns>
399-
public virtual T Compare<T>(IEnumerable<string> paths, bool includeUntracked) where T : class
392+
public virtual T Compare<T>(IEnumerable<string> paths, bool includeUntracked) where T : class, IDiffResult
400393
{
401394
return Compare<T>(includeUntracked ? DiffModifiers.IncludeUntracked : DiffModifiers.None, paths);
402395
}
@@ -417,7 +410,7 @@ public virtual T Compare<T>(IEnumerable<string> paths, bool includeUntracked) wh
417410
/// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or
418411
/// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam>
419412
/// <returns>A <typeparamref name="T"/> containing the changes between the working directory and the index.</returns>
420-
public virtual T Compare<T>(IEnumerable<string> paths, bool includeUntracked, ExplicitPathsOptions explicitPathsOptions) where T : class
413+
public virtual T Compare<T>(IEnumerable<string> paths, bool includeUntracked, ExplicitPathsOptions explicitPathsOptions) where T : class, IDiffResult
421414
{
422415
return Compare<T>(includeUntracked ? DiffModifiers.IncludeUntracked : DiffModifiers.None, paths, explicitPathsOptions);
423416
}
@@ -443,7 +436,7 @@ public virtual T Compare<T>(
443436
IEnumerable<string> paths,
444437
bool includeUntracked,
445438
ExplicitPathsOptions explicitPathsOptions,
446-
CompareOptions compareOptions) where T : class
439+
CompareOptions compareOptions) where T : class, IDiffResult
447440
{
448441
return Compare<T>(includeUntracked ? DiffModifiers.IncludeUntracked : DiffModifiers.None, paths, explicitPathsOptions, compareOptions);
449442
}
@@ -452,19 +445,8 @@ internal virtual T Compare<T>(
452445
DiffModifiers diffOptions,
453446
IEnumerable<string> paths = null,
454447
ExplicitPathsOptions explicitPathsOptions = null,
455-
CompareOptions compareOptions = null) where T : class
448+
CompareOptions compareOptions = null) where T : class, IDiffResult
456449
{
457-
Func<DiffSafeHandle, object> builder;
458-
459-
if (!ChangesBuilders.TryGetValue(typeof(T), out builder))
460-
{
461-
throw new LibGit2SharpException(CultureInfo.InvariantCulture,
462-
"Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.",
463-
typeof(T),
464-
typeof(TreeChanges),
465-
typeof(Patch));
466-
}
467-
468450
var comparer = WorkdirToIndex(repo);
469451

470452
if (explicitPathsOptions != null)
@@ -479,7 +461,7 @@ internal virtual T Compare<T>(
479461

480462
using (DiffSafeHandle diff = BuildDiffList(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions))
481463
{
482-
return (T)builder(diff);
464+
return BuildDiffResult<T>(diff);
483465
}
484466
}
485467

LibGit2Sharp/IDiffResult.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace LibGit2Sharp
2+
{
3+
public interface IDiffResult
4+
{ }
5+
}

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@
380380
<Compile Include="Core\GitCertificateSsh.cs" />
381381
<Compile Include="Core\GitCertificateSshType.cs" />
382382
<Compile Include="CertificateSsh.cs" />
383+
<Compile Include="IDiffResult.cs" />
383384
</ItemGroup>
384385
<ItemGroup>
385386
<CodeAnalysisDictionary Include="CustomDictionary.xml" />

LibGit2Sharp/Patch.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace LibGit2Sharp
1616
/// deleted, modified, ..., then consider using a simpler <see cref="TreeChanges"/>.</para>
1717
/// </summary>
1818
[DebuggerDisplay("{DebuggerDisplay,nq}")]
19-
public class Patch : IEnumerable<PatchEntryChanges>
19+
public class Patch : IEnumerable<PatchEntryChanges>, IDiffResult
2020
{
2121
private readonly StringBuilder fullPatchBuilder = new StringBuilder();
2222

@@ -41,7 +41,6 @@ internal Patch(DiffSafeHandle diff)
4141
AddFileChange(delta);
4242
Proxy.git_patch_print(patch, PrintCallBack);
4343
}
44-
4544
}
4645
}
4746

LibGit2Sharp/PatchStats.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace LibGit2Sharp
1313
/// <para>The individual patches for each file can be accessed through the indexer of this class.</para>
1414
/// </summary>
1515
[DebuggerDisplay("{DebuggerDisplay,nq}")]
16-
public class PatchStats : IEnumerable<ContentChangeStats>
16+
public class PatchStats : IEnumerable<ContentChangeStats>, IDiffResult
1717
{
1818
private readonly IDictionary<FilePath, ContentChangeStats> changes = new Dictionary<FilePath, ContentChangeStats>();
1919
private readonly int totalLinesAdded;

LibGit2Sharp/TreeChanges.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace LibGit2Sharp
1515
/// <para>To obtain the actual patch of the diff, use the <see cref="Patch"/> class when calling Compare.</para>.
1616
/// </summary>
1717
[DebuggerDisplay("{DebuggerDisplay,nq}")]
18-
public class TreeChanges : IEnumerable<TreeEntryChanges>
18+
public class TreeChanges : IEnumerable<TreeEntryChanges>, IDiffResult
1919
{
2020
private readonly List<TreeEntryChanges> changes = new List<TreeEntryChanges>();
2121
private readonly List<TreeEntryChanges> added = new List<TreeEntryChanges>();
@@ -91,7 +91,6 @@ IEnumerator IEnumerable.GetEnumerator()
9191

9292
#endregion
9393

94-
9594
/// <summary>
9695
/// List of <see cref="TreeEntryChanges"/> that have been been added.
9796
/// </summary>

0 commit comments

Comments
 (0)
0