diff --git a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs index 0e8ef905e..bebbdded0 100644 --- a/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs +++ b/LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs @@ -1123,17 +1123,6 @@ public void RetrievingDiffChangesMustAlwaysBeCaseSensitive() } } - [Fact] - public void CallingCompareWithAnUnsupportedGenericParamThrows() - { - var path = SandboxStandardTestRepoGitDir(); - using (var repo = new Repository(path)) - { - Assert.Throws(() => repo.Diff.Compare(default(Tree), default(Tree))); - Assert.Throws(() => repo.Diff.Compare()); - } - } - [Fact] public void UsingPatienceAlgorithmCompareOptionProducesPatienceDiff() { diff --git a/LibGit2Sharp.Tests/MetaFixture.cs b/LibGit2Sharp.Tests/MetaFixture.cs index a9b6b06c8..057c9a1d4 100644 --- a/LibGit2Sharp.Tests/MetaFixture.cs +++ b/LibGit2Sharp.Tests/MetaFixture.cs @@ -17,7 +17,7 @@ public class MetaFixture { private static readonly HashSet explicitOnlyInterfaces = new HashSet { - typeof(IBelongToARepository), + typeof(IBelongToARepository), typeof(IDiffResult), }; [Fact] @@ -401,6 +401,20 @@ where method.IsDefined(typeof(ExtensionAttribute), false) select method; return query; } + + [Fact] + public void AllIDiffResultsAreInChangesBuilder() + { + var diff = typeof(Diff).GetField("ChangesBuilders", BindingFlags.NonPublic | BindingFlags.Static); + var changesBuilders = (System.Collections.IDictionary)diff.GetValue(null); + + IEnumerable diffResults = typeof(Diff).Assembly.GetExportedTypes() + .Where(type => type.GetInterface("IDiffResult") != null); + + var nonBuilderTypes = diffResults.Where(diffResult => !changesBuilders.Contains(diffResult)); + Assert.False(nonBuilderTypes.Any(), "Classes which implement IDiffResult but are not registered under ChangesBuilders in Diff:" + Environment.NewLine + + string.Join(Environment.NewLine, nonBuilderTypes.Select(type => type.FullName))); + } } internal static class TypeExtensions diff --git a/LibGit2Sharp/Diff.cs b/LibGit2Sharp/Diff.cs index d8e8830c2..1e8d283c6 100644 --- a/LibGit2Sharp/Diff.cs +++ b/LibGit2Sharp/Diff.cs @@ -102,6 +102,21 @@ private static IDictionary new PatchStats(diff) }, }; + + private static T BuildDiffResult(DiffSafeHandle diff) where T : class, IDiffResult + { + Func builder; + + if (!ChangesBuilders.TryGetValue(typeof(T), out builder)) + { + throw new LibGit2SharpException(CultureInfo.InvariantCulture, + "User-defined types passed to Compare are not supported. Supported values are: {0}", + string.Join(", ", ChangesBuilders.Keys.Select(x => x.Name))); + } + + return (T)builder(diff); + } + /// /// Show changes between two s. /// @@ -134,7 +149,7 @@ public virtual ContentChanges Compare(Blob oldBlob, Blob newBlob, CompareOptions /// The you want to compare from. /// The you want to compare to. /// A containing the changes between the and the . - public virtual T Compare(Tree oldTree, Tree newTree) where T : class + public virtual T Compare(Tree oldTree, Tree newTree) where T : class, IDiffResult { return Compare(oldTree, newTree, null, null, null); } @@ -146,7 +161,7 @@ public virtual T Compare(Tree oldTree, Tree newTree) where T : class /// The you want to compare to. /// The list of paths (either files or directories) that should be compared. /// A containing the changes between the and the . - public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable paths) where T : class + public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable paths) where T : class, IDiffResult { return Compare(oldTree, newTree, paths, null, null); } @@ -163,7 +178,7 @@ public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable path /// /// A containing the changes between the and the . public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable paths, - ExplicitPathsOptions explicitPathsOptions) where T : class + ExplicitPathsOptions explicitPathsOptions) where T : class, IDiffResult { return Compare(oldTree, newTree, paths, explicitPathsOptions, null); } @@ -176,7 +191,7 @@ public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable path /// The list of paths (either files or directories) that should be compared. /// Additional options to define patch generation behavior. /// A containing the changes between the and the . - public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable paths, CompareOptions compareOptions) where T : class + public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable paths, CompareOptions compareOptions) where T : class, IDiffResult { return Compare(oldTree, newTree, paths, null, compareOptions); } @@ -188,7 +203,7 @@ public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable path /// The you want to compare to. /// Additional options to define patch generation behavior. /// A containing the changes between the and the . - public virtual T Compare(Tree oldTree, Tree newTree, CompareOptions compareOptions) where T : class + public virtual T Compare(Tree oldTree, Tree newTree, CompareOptions compareOptions) where T : class, IDiffResult { return Compare(oldTree, newTree, null, null, compareOptions); } @@ -206,19 +221,8 @@ public virtual T Compare(Tree oldTree, Tree newTree, CompareOptions compareOp /// Additional options to define patch generation behavior. /// A containing the changes between the and the . public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable paths, ExplicitPathsOptions explicitPathsOptions, - CompareOptions compareOptions) where T : class + CompareOptions compareOptions) where T : class, IDiffResult { - Func builder; - - if (!ChangesBuilders.TryGetValue(typeof(T), out builder)) - { - throw new LibGit2SharpException(CultureInfo.InvariantCulture, - "Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.", - typeof(T), - typeof(TreeChanges), - typeof(Patch)); - } - var comparer = TreeToTree(repo); ObjectId oldTreeId = oldTree != null ? oldTree.Id : null; ObjectId newTreeId = newTree != null ? newTree.Id : null; @@ -236,7 +240,7 @@ public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable path using (DiffSafeHandle diff = BuildDiffList(oldTreeId, newTreeId, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)) { - return (T)builder(diff); + return BuildDiffResult(diff); } } @@ -252,7 +256,7 @@ public virtual T Compare(Tree oldTree, Tree newTree, IEnumerable path /// Can be either a if you are only interested in the list of files modified, added, ..., or /// a if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the and the selected target. - public virtual T Compare(Tree oldTree, DiffTargets diffTargets) where T : class + public virtual T Compare(Tree oldTree, DiffTargets diffTargets) where T : class, IDiffResult { return Compare(oldTree, diffTargets, null, null, null); } @@ -270,7 +274,7 @@ public virtual T Compare(Tree oldTree, DiffTargets diffTargets) where T : cla /// Can be either a if you are only interested in the list of files modified, added, ..., or /// a if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the and the selected target. - public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable paths) where T : class + public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable paths) where T : class, IDiffResult { return Compare(oldTree, diffTargets, paths, null, null); } @@ -293,7 +297,7 @@ public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the and the selected target. public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable paths, - ExplicitPathsOptions explicitPathsOptions) where T : class + ExplicitPathsOptions explicitPathsOptions) where T : class, IDiffResult { return Compare(oldTree, diffTargets, paths, explicitPathsOptions, null); } @@ -317,19 +321,8 @@ public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the and the selected target. public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable paths, - ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) where T : class + ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) where T : class, IDiffResult { - Func builder; - - if (!ChangesBuilders.TryGetValue(typeof(T), out builder)) - { - throw new LibGit2SharpException(CultureInfo.InvariantCulture, - "Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.", - typeof(T), - typeof(TreeChanges), - typeof(Patch)); - } - var comparer = HandleRetrieverDispatcher[diffTargets](repo); ObjectId oldTreeId = oldTree != null ? oldTree.Id : null; @@ -349,7 +342,7 @@ public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable(diff); } } @@ -363,7 +356,7 @@ public virtual T Compare(Tree oldTree, DiffTargets diffTargets, IEnumerableCan be either a if you are only interested in the list of files modified, added, ..., or /// a if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the working directory and the index. - public virtual T Compare() where T : class + public virtual T Compare() where T : class, IDiffResult { return Compare(DiffModifiers.None); } @@ -379,7 +372,7 @@ public virtual T Compare() where T : class /// Can be either a if you are only interested in the list of files modified, added, ..., or /// a if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the working directory and the index. - public virtual T Compare(IEnumerable paths) where T : class + public virtual T Compare(IEnumerable paths) where T : class, IDiffResult { return Compare(DiffModifiers.None, paths); } @@ -396,7 +389,7 @@ public virtual T Compare(IEnumerable paths) where T : class /// Can be either a if you are only interested in the list of files modified, added, ..., or /// a if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the working directory and the index. - public virtual T Compare(IEnumerable paths, bool includeUntracked) where T : class + public virtual T Compare(IEnumerable paths, bool includeUntracked) where T : class, IDiffResult { return Compare(includeUntracked ? DiffModifiers.IncludeUntracked : DiffModifiers.None, paths); } @@ -417,7 +410,7 @@ public virtual T Compare(IEnumerable paths, bool includeUntracked) wh /// Can be either a if you are only interested in the list of files modified, added, ..., or /// a if you want the actual patch content for the whole diff and for individual files. /// A containing the changes between the working directory and the index. - public virtual T Compare(IEnumerable paths, bool includeUntracked, ExplicitPathsOptions explicitPathsOptions) where T : class + public virtual T Compare(IEnumerable paths, bool includeUntracked, ExplicitPathsOptions explicitPathsOptions) where T : class, IDiffResult { return Compare(includeUntracked ? DiffModifiers.IncludeUntracked : DiffModifiers.None, paths, explicitPathsOptions); } @@ -443,7 +436,7 @@ public virtual T Compare( IEnumerable paths, bool includeUntracked, ExplicitPathsOptions explicitPathsOptions, - CompareOptions compareOptions) where T : class + CompareOptions compareOptions) where T : class, IDiffResult { return Compare(includeUntracked ? DiffModifiers.IncludeUntracked : DiffModifiers.None, paths, explicitPathsOptions, compareOptions); } @@ -452,19 +445,8 @@ internal virtual T Compare( DiffModifiers diffOptions, IEnumerable paths = null, ExplicitPathsOptions explicitPathsOptions = null, - CompareOptions compareOptions = null) where T : class + CompareOptions compareOptions = null) where T : class, IDiffResult { - Func builder; - - if (!ChangesBuilders.TryGetValue(typeof(T), out builder)) - { - throw new LibGit2SharpException(CultureInfo.InvariantCulture, - "Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.", - typeof(T), - typeof(TreeChanges), - typeof(Patch)); - } - var comparer = WorkdirToIndex(repo); if (explicitPathsOptions != null) @@ -479,7 +461,7 @@ internal virtual T Compare( using (DiffSafeHandle diff = BuildDiffList(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)) { - return (T)builder(diff); + return BuildDiffResult(diff); } } diff --git a/LibGit2Sharp/IDiffResult.cs b/LibGit2Sharp/IDiffResult.cs new file mode 100644 index 000000000..fdd4a5c8f --- /dev/null +++ b/LibGit2Sharp/IDiffResult.cs @@ -0,0 +1,5 @@ +namespace LibGit2Sharp +{ + public interface IDiffResult + { } +} diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 195612b36..561ad7676 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -380,6 +380,7 @@ + diff --git a/LibGit2Sharp/Patch.cs b/LibGit2Sharp/Patch.cs index c437f4d31..fce96e105 100644 --- a/LibGit2Sharp/Patch.cs +++ b/LibGit2Sharp/Patch.cs @@ -16,7 +16,7 @@ namespace LibGit2Sharp /// deleted, modified, ..., then consider using a simpler . /// [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class Patch : IEnumerable + public class Patch : IEnumerable, IDiffResult { private readonly StringBuilder fullPatchBuilder = new StringBuilder(); @@ -41,7 +41,6 @@ internal Patch(DiffSafeHandle diff) AddFileChange(delta); Proxy.git_patch_print(patch, PrintCallBack); } - } } diff --git a/LibGit2Sharp/PatchStats.cs b/LibGit2Sharp/PatchStats.cs index da92ac07f..fc16d303d 100644 --- a/LibGit2Sharp/PatchStats.cs +++ b/LibGit2Sharp/PatchStats.cs @@ -13,7 +13,7 @@ namespace LibGit2Sharp /// The individual patches for each file can be accessed through the indexer of this class. /// [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class PatchStats : IEnumerable + public class PatchStats : IEnumerable, IDiffResult { private readonly IDictionary changes = new Dictionary(); private readonly int totalLinesAdded; diff --git a/LibGit2Sharp/TreeChanges.cs b/LibGit2Sharp/TreeChanges.cs index 39a0097ee..dcf788556 100644 --- a/LibGit2Sharp/TreeChanges.cs +++ b/LibGit2Sharp/TreeChanges.cs @@ -15,7 +15,7 @@ namespace LibGit2Sharp /// To obtain the actual patch of the diff, use the class when calling Compare.. /// [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class TreeChanges : IEnumerable + public class TreeChanges : IEnumerable, IDiffResult { private readonly List changes = new List(); private readonly List added = new List(); @@ -91,7 +91,6 @@ IEnumerator IEnumerable.GetEnumerator() #endregion - /// /// List of that have been been added. ///