From 8621986b66adc72717719de1c58a7059b0277932 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 18 Nov 2022 17:29:45 +0100 Subject: [PATCH 01/60] WIP --- .../RepoM.Core.Plugin.csproj | 2 +- .../RepositoryViewSort/IRepositoryComparer.cs | 185 ++++++++++++++++++ 2 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs diff --git a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj index 21feb56d..32163da6 100644 --- a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj +++ b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 diff --git a/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs b/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs new file mode 100644 index 00000000..6c884b01 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs @@ -0,0 +1,185 @@ +namespace RepoM.Core.Plugin.RepositoryViewSort; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Transactions; + +public interface IRepositoryComparer : IComparer +{ +} + +public class SumCompositionComparer : IRepositoryComparer +{ + private readonly IRepositoryComparer[] _comparers; + + public SumCompositionComparer(IEnumerable comparers) + { + _comparers = comparers.ToArray(); + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return _comparers.Sum(c => c.Compare(x, y)); + } +} + +public class CompositionComparer : IRepositoryComparer +{ + private readonly IRepositoryComparer[] _comparers; + + public CompositionComparer(IEnumerable comparers) + { + _comparers = comparers.ToArray(); + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return _comparers.Select(c => c.Compare(x, y)).FirstOrDefault(result => result != 0); + } +} + + + + +public class IsPinnedComparer : IRepositoryComparer +{ + private readonly int _weight; + + public IsPinnedComparer(int weight) + { + if (weight <= 0) + { + throw new ArgumentOutOfRangeException(nameof(weight), "Should be positive"); + } + + _weight = weight; + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return (x.IsPinned.CompareTo(y.IsPinned) * _weight); + } +} + +public class AzComparer : IRepositoryComparer +{ + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + var nameComparison = string.Compare(x.Name, y.Name, StringComparison.Ordinal); + + if (nameComparison < 0) + { + return -1; + } + + if (nameComparison == 0) + { + return 0; + } + + return 1; + + if (nameComparison != 0) + { + return nameComparison; + } + + // var currentBranchComparison = string.Compare(x.CurrentBranch, y.CurrentBranch, StringComparison.Ordinal); + // if (currentBranchComparison != 0) + // { + // return currentBranchComparison; + // } + // + // var pathComparison = string.Compare(x.Path, y.Path, StringComparison.Ordinal); + // if (pathComparison != 0) + // { + // return pathComparison; + // } + // + // var isPinnedComparison = x.IsPinned.CompareTo(y.IsPinned); + // if (isPinnedComparison != 0) + // { + // return isPinnedComparison; + // } + // + // return x.HasUnpushedChanges.CompareTo(y.HasUnpushedChanges); + } +} + +public interface IRepositoryComparerFactory +{ +} + +public interface IPluginRepository +{ + string Name { get; } + + string CurrentBranch { get; } + + string Path { get; } + + bool IsPinned { get; } + + bool HasUnpushedChanges { get; } +} \ No newline at end of file From efdd25d65aa0d20a76b3c0515c8a6970016f8095 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 21 Nov 2022 18:48:52 +0100 Subject: [PATCH 02/60] poc --- RepoM.sln | 22 +++ .../RepositoryViewSort/IRepositoryComparer.cs | 55 ++++++- .../TestFramework/VerifierInitializer.cs | 15 ++ tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj | 38 +++++ tests/Yaml.Poc.Tests/YamlTests.cs | 148 ++++++++++++++++++ 5 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs create mode 100644 tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj create mode 100644 tests/Yaml.Poc.Tests/YamlTests.cs diff --git a/RepoM.sln b/RepoM.sln index 5802ec6e..fbf46806 100644 --- a/RepoM.sln +++ b/RepoM.sln @@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Api.Tests", "tests\Re EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Core.Plugin", "src\RepoM.Core.Plugin\RepoM.Core.Plugin.csproj", "{E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yaml.Poc.Tests", "tests\Yaml.Poc.Tests\Yaml.Poc.Tests.csproj", "{C5A65FD2-CD65-47EA-A521-8B7C756AC986}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -327,6 +329,26 @@ Global {E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}.Release|x64.Build.0 = Release|Any CPU {E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}.Release|x86.ActiveCfg = Release|Any CPU {E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}.Release|x86.Build.0 = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM.Build.0 = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM64.Build.0 = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x64.ActiveCfg = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x64.Build.0 = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x86.ActiveCfg = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x86.Build.0 = Debug|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|Any CPU.Build.0 = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM.ActiveCfg = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM.Build.0 = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM64.ActiveCfg = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM64.Build.0 = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x64.ActiveCfg = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x64.Build.0 = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x86.ActiveCfg = Release|Any CPU + {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs b/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs index 6c884b01..b64db3dc 100644 --- a/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs @@ -3,12 +3,63 @@ namespace RepoM.Core.Plugin.RepositoryViewSort; using System; using System.Collections.Generic; using System.Linq; -using System.Transactions; public interface IRepositoryComparer : IComparer { } +public interface IRepositoryScoreCalculator +{ + int Score(IPluginRepository repository); +} + +public class IsPinnedScoreCalculator : IRepositoryScoreCalculator +{ + private readonly int _weight; + + public IsPinnedScoreCalculator(int weight) + { + _weight = weight; + } + + public int Score(IPluginRepository repository) + { + return repository.IsPinned ? _weight : 0; + } +} + + +public class ScoreComparer : IRepositoryComparer +{ + private readonly IRepositoryScoreCalculator _calculator; + + public ScoreComparer(IRepositoryScoreCalculator calculator) + { + _calculator = calculator ?? throw new ArgumentNullException(nameof(calculator)); + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return _calculator.Score(x) - _calculator.Score(y); + } +} + + public class SumCompositionComparer : IRepositoryComparer { private readonly IRepositoryComparer[] _comparers; @@ -70,8 +121,6 @@ public int Compare(IPluginRepository x, IPluginRepository y) } - - public class IsPinnedComparer : IRepositoryComparer { private readonly int _weight; diff --git a/tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs b/tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs new file mode 100644 index 00000000..b2d0afc3 --- /dev/null +++ b/tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs @@ -0,0 +1,15 @@ +namespace Yaml.Poc.Tests.TestFramework; + +using System.Runtime.CompilerServices; +using Argon; +using VerifyTests; + +public static class VerifierInitializer +{ + [ModuleInitializer] + public static void Initialize() + { + VerifierSettings.DisableRequireUniquePrefix(); + VerifierSettings.AddExtraSettings(serializerSettings => serializerSettings.TypeNameHandling = TypeNameHandling.Auto); + } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj new file mode 100644 index 00000000..0a183436 --- /dev/null +++ b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj @@ -0,0 +1,38 @@ + + + + net6.0 + false + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs new file mode 100644 index 00000000..46de1cb4 --- /dev/null +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -0,0 +1,148 @@ +namespace Yaml.Poc.Tests; + +using System; +using System.Collections; +using System.Collections.Generic; +using Xunit; +using YamlDotNet.Core; +using YamlDotNet.Core.Events; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; +using YamlDotNet.Serialization.NodeDeserializers; +using YamlDotNet.Serialization.NodeTypeResolvers; + + +/// +/// Configuration to compare two repos +/// +public interface ICompareReposData +{ +} + +// SumCompositionComparer@1 +public class SumCompositionComparerV1Data : ICompareReposData +{ + public List Items { get; set; } +} + +// ScoreComparer@1 +public class ScoreComparerV1Data : ICompareReposData +{ + public IScoreRepoData Score { get; set; } +} + +// AlphabetComparer@1 +public class AlphabetComparerV1Data : ICompareReposData +{ + public string Property { get; set; } + + public int Weight { get; set; } +} + +/// +/// Configuration to score a single repo +/// +public interface IScoreRepoData +{ +} + +// IsPinnedScorer@1 +public class IsPinnedScorerV1Data : IScoreRepoData +{ + public int Weight { get; set; } +} + + + + +public class YamlTests +{ + //https://github.com/aaubry/YamlDotNet/wiki/Serialization.Deserializer + [Fact] + public void Abc() + { + string yml1 = @" +- !contact@1 + Name: Oz-Ware + PhoneNumber: 123456789 +- !repo-score-provider@1 + Score: + - provider: isPinned@1 + weight: 5"; + + string yml = @" + !sum-comparer@1 + items: + - !alphabet-comparer@1 + property: Name + weight: 5 + - !score-comparer@1 + score: + !is-pinned-scorer@1 + weight: 5 +"; + + var deserializer = new DeserializerBuilder() + .WithNamingConvention(HyphenatedNamingConvention.Instance) + .WithTagMapping("!score-comparer@1", typeof(ScoreComparerV1Data)) + .WithTagMapping("!alphabet-comparer@1", typeof(AlphabetComparerV1Data)) + .WithTagMapping("!is-pinned-scorer@1", typeof(IsPinnedScorerV1Data)) + + + // .WithTagMapping("!repo-score-provider@1", typeof(RepoScoreProvider)) + // .WithAttributeOverride( + // c => c.Name, + // new YamlMemberAttribute + // { + // Alias = "full_name", + // }) + // .WithTypeConverter(wrapped => + // { + // return new Coen(wrapped); + // }, + // syntax => { }) + // .WithTypeInspector(inspector => + // { + // return inspector; + // }) + // .WithNodeDeserializer( + // inner => new ValidatingNodeDeserializer(inner), + // s => s.InsteadOf() + // ) + // .WithNodeTypeResolver(inner => new SystemTypeFromTagNodeTypeResolver(inner), + // s => s.InsteadOf() + // ) + .Build(); + + var result = deserializer.Deserialize(yml); + + + + } +} + +public class SystemTypeFromTagNodeTypeResolver : INodeTypeResolver +{ + public SystemTypeFromTagNodeTypeResolver(INodeTypeResolver inner) + { + //throw new NotImplementedException(); + } + + public bool Resolve(NodeEvent nodeEvent, ref Type currentType) + { + if (nodeEvent.Tag.Value.StartsWith("!clr:")) + { + var netTypeName = nodeEvent.Tag.Value.Substring(5); + var type = Type.GetType(netTypeName); + if (type != null) + { + currentType = type; + return true; + } + } + + return false; + } +} + + From 3f8b9aebf36cc20c207f2bbacaec565060d4e7d1 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 21 Nov 2022 20:12:53 +0100 Subject: [PATCH 03/60] wip --- .../ICompareReposConfiguration.cs | 8 + .../RepositoryOrdering/IPluginRepository.cs | 14 ++ .../IRepoScorerConfiguration.cs | 8 + .../RepositoryOrdering/IRepositoryComparer.cs | 7 + .../IRepositoryComparerFactory.cs | 5 + .../IRepositoryScoreCalculator.cs | 6 + .../Implementations/AzComparer.cs | 63 +++++ .../Implementations/CompositionComparer.cs | 34 +++ .../Implementations/IsPinnedComparer.cs | 38 +++ .../IsPinnedScoreCalculator.cs | 16 ++ .../Implementations/ScoreComparer.cs | 33 +++ .../Implementations/SumCompositionComparer.cs | 34 +++ .../RepositoryViewSort/IRepositoryComparer.cs | 234 ------------------ .../AlphabetComparerConfigurationV1.cs | 10 + .../IsPinnedScorerConfigurationV1.cs | 8 + .../ScoreComparerConfigurationV1.cs | 8 + .../SumComparerConfigurationV1.cs | 9 + tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj | 4 + .../Yaml.Poc.Tests/YamlTests.Abc.verified.txt | 16 ++ tests/Yaml.Poc.Tests/YamlTests.cs | 145 ++--------- 20 files changed, 340 insertions(+), 360 deletions(-) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AzComparer.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/CompositionComparer.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScoreCalculator.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparer.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumCompositionComparer.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs create mode 100644 tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs create mode 100644 tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs create mode 100644 tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs create mode 100644 tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs create mode 100644 tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs new file mode 100644 index 00000000..c3bc3504 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs @@ -0,0 +1,8 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering; + +/// +/// Configuration to compare two repos +/// +public interface ICompareReposConfiguration +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs new file mode 100644 index 00000000..1d2d05e9 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs @@ -0,0 +1,14 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering; + +public interface IPluginRepository +{ + string Name { get; } + + string CurrentBranch { get; } + + string Path { get; } + + bool IsPinned { get; } + + bool HasUnpushedChanges { get; } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs new file mode 100644 index 00000000..01be63cb --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs @@ -0,0 +1,8 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering; + +/// +/// Configuration to score a single repo +/// +public interface IRepoScorerConfiguration +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs new file mode 100644 index 00000000..84fea17c --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs @@ -0,0 +1,7 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering; + +using System.Collections.Generic; + +public interface IRepositoryComparer : IComparer +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs new file mode 100644 index 00000000..696d9796 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs @@ -0,0 +1,5 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering; + +public interface IRepositoryComparerFactory +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs new file mode 100644 index 00000000..67e6eb5a --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs @@ -0,0 +1,6 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering; + +public interface IRepositoryScoreCalculator +{ + int Score(IPluginRepository repository); +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AzComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AzComparer.cs new file mode 100644 index 00000000..6b41bd73 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AzComparer.cs @@ -0,0 +1,63 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; + +using System; + +public class AzComparer : IRepositoryComparer +{ + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + var nameComparison = string.Compare(x.Name, y.Name, StringComparison.Ordinal); + + if (nameComparison < 0) + { + return -1; + } + + if (nameComparison == 0) + { + return 0; + } + + return 1; + + if (nameComparison != 0) + { + return nameComparison; + } + + // var currentBranchComparison = string.Compare(x.CurrentBranch, y.CurrentBranch, StringComparison.Ordinal); + // if (currentBranchComparison != 0) + // { + // return currentBranchComparison; + // } + // + // var pathComparison = string.Compare(x.Path, y.Path, StringComparison.Ordinal); + // if (pathComparison != 0) + // { + // return pathComparison; + // } + // + // var isPinnedComparison = x.IsPinned.CompareTo(y.IsPinned); + // if (isPinnedComparison != 0) + // { + // return isPinnedComparison; + // } + // + // return x.HasUnpushedChanges.CompareTo(y.HasUnpushedChanges); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/CompositionComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/CompositionComparer.cs new file mode 100644 index 00000000..347aed51 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/CompositionComparer.cs @@ -0,0 +1,34 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; + +using System.Collections.Generic; +using System.Linq; + +public class CompositionComparer : IRepositoryComparer +{ + private readonly IRepositoryComparer[] _comparers; + + public CompositionComparer(IEnumerable comparers) + { + _comparers = comparers.ToArray(); + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return _comparers.Select(c => c.Compare(x, y)).FirstOrDefault(result => result != 0); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs new file mode 100644 index 00000000..6f395cea --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs @@ -0,0 +1,38 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; + +using System; + +public class IsPinnedComparer : IRepositoryComparer +{ + private readonly int _weight; + + public IsPinnedComparer(int weight) + { + if (weight <= 0) + { + throw new ArgumentOutOfRangeException(nameof(weight), "Should be positive"); + } + + _weight = weight; + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return x.IsPinned.CompareTo(y.IsPinned) * _weight; + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScoreCalculator.cs new file mode 100644 index 00000000..e81635c5 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScoreCalculator.cs @@ -0,0 +1,16 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; + +public class IsPinnedScoreCalculator : IRepositoryScoreCalculator +{ + private readonly int _weight; + + public IsPinnedScoreCalculator(int weight) + { + _weight = weight; + } + + public int Score(IPluginRepository repository) + { + return repository.IsPinned ? _weight : 0; + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparer.cs new file mode 100644 index 00000000..04e924ca --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparer.cs @@ -0,0 +1,33 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; + +using System; + +public class ScoreComparer : IRepositoryComparer +{ + private readonly IRepositoryScoreCalculator _calculator; + + public ScoreComparer(IRepositoryScoreCalculator calculator) + { + _calculator = calculator ?? throw new ArgumentNullException(nameof(calculator)); + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return _calculator.Score(x) - _calculator.Score(y); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumCompositionComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumCompositionComparer.cs new file mode 100644 index 00000000..97f5d8b5 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumCompositionComparer.cs @@ -0,0 +1,34 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; + +using System.Collections.Generic; +using System.Linq; + +public class SumCompositionComparer : IRepositoryComparer +{ + private readonly IRepositoryComparer[] _comparers; + + public SumCompositionComparer(IEnumerable comparers) + { + _comparers = comparers.ToArray(); + } + + public int Compare(IPluginRepository x, IPluginRepository y) + { + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return 1; + } + + if (ReferenceEquals(null, x)) + { + return -1; + } + + return _comparers.Sum(c => c.Compare(x, y)); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs b/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs deleted file mode 100644 index b64db3dc..00000000 --- a/src/RepoM.Core.Plugin/RepositoryViewSort/IRepositoryComparer.cs +++ /dev/null @@ -1,234 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryViewSort; - -using System; -using System.Collections.Generic; -using System.Linq; - -public interface IRepositoryComparer : IComparer -{ -} - -public interface IRepositoryScoreCalculator -{ - int Score(IPluginRepository repository); -} - -public class IsPinnedScoreCalculator : IRepositoryScoreCalculator -{ - private readonly int _weight; - - public IsPinnedScoreCalculator(int weight) - { - _weight = weight; - } - - public int Score(IPluginRepository repository) - { - return repository.IsPinned ? _weight : 0; - } -} - - -public class ScoreComparer : IRepositoryComparer -{ - private readonly IRepositoryScoreCalculator _calculator; - - public ScoreComparer(IRepositoryScoreCalculator calculator) - { - _calculator = calculator ?? throw new ArgumentNullException(nameof(calculator)); - } - - public int Compare(IPluginRepository x, IPluginRepository y) - { - if (ReferenceEquals(x, y)) - { - return 0; - } - - if (ReferenceEquals(null, y)) - { - return 1; - } - - if (ReferenceEquals(null, x)) - { - return -1; - } - - return _calculator.Score(x) - _calculator.Score(y); - } -} - - -public class SumCompositionComparer : IRepositoryComparer -{ - private readonly IRepositoryComparer[] _comparers; - - public SumCompositionComparer(IEnumerable comparers) - { - _comparers = comparers.ToArray(); - } - - public int Compare(IPluginRepository x, IPluginRepository y) - { - if (ReferenceEquals(x, y)) - { - return 0; - } - - if (ReferenceEquals(null, y)) - { - return 1; - } - - if (ReferenceEquals(null, x)) - { - return -1; - } - - return _comparers.Sum(c => c.Compare(x, y)); - } -} - -public class CompositionComparer : IRepositoryComparer -{ - private readonly IRepositoryComparer[] _comparers; - - public CompositionComparer(IEnumerable comparers) - { - _comparers = comparers.ToArray(); - } - - public int Compare(IPluginRepository x, IPluginRepository y) - { - if (ReferenceEquals(x, y)) - { - return 0; - } - - if (ReferenceEquals(null, y)) - { - return 1; - } - - if (ReferenceEquals(null, x)) - { - return -1; - } - - return _comparers.Select(c => c.Compare(x, y)).FirstOrDefault(result => result != 0); - } -} - - -public class IsPinnedComparer : IRepositoryComparer -{ - private readonly int _weight; - - public IsPinnedComparer(int weight) - { - if (weight <= 0) - { - throw new ArgumentOutOfRangeException(nameof(weight), "Should be positive"); - } - - _weight = weight; - } - - public int Compare(IPluginRepository x, IPluginRepository y) - { - if (ReferenceEquals(x, y)) - { - return 0; - } - - if (ReferenceEquals(null, y)) - { - return 1; - } - - if (ReferenceEquals(null, x)) - { - return -1; - } - - return (x.IsPinned.CompareTo(y.IsPinned) * _weight); - } -} - -public class AzComparer : IRepositoryComparer -{ - public int Compare(IPluginRepository x, IPluginRepository y) - { - if (ReferenceEquals(x, y)) - { - return 0; - } - - if (ReferenceEquals(null, y)) - { - return 1; - } - - if (ReferenceEquals(null, x)) - { - return -1; - } - - var nameComparison = string.Compare(x.Name, y.Name, StringComparison.Ordinal); - - if (nameComparison < 0) - { - return -1; - } - - if (nameComparison == 0) - { - return 0; - } - - return 1; - - if (nameComparison != 0) - { - return nameComparison; - } - - // var currentBranchComparison = string.Compare(x.CurrentBranch, y.CurrentBranch, StringComparison.Ordinal); - // if (currentBranchComparison != 0) - // { - // return currentBranchComparison; - // } - // - // var pathComparison = string.Compare(x.Path, y.Path, StringComparison.Ordinal); - // if (pathComparison != 0) - // { - // return pathComparison; - // } - // - // var isPinnedComparison = x.IsPinned.CompareTo(y.IsPinned); - // if (isPinnedComparison != 0) - // { - // return isPinnedComparison; - // } - // - // return x.HasUnpushedChanges.CompareTo(y.HasUnpushedChanges); - } -} - -public interface IRepositoryComparerFactory -{ -} - -public interface IPluginRepository -{ - string Name { get; } - - string CurrentBranch { get; } - - string Path { get; } - - bool IsPinned { get; } - - bool HasUnpushedChanges { get; } -} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs new file mode 100644 index 00000000..119fa16c --- /dev/null +++ b/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs @@ -0,0 +1,10 @@ +namespace Yaml.Poc.Tests; + +using RepoM.Core.Plugin.RepositoryOrdering; + +public class AlphabetComparerConfigurationV1 : ICompareReposConfiguration +{ + public string? Property { get; set; } + + public int Weight { get; set; } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs b/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs new file mode 100644 index 00000000..0bca34f3 --- /dev/null +++ b/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs @@ -0,0 +1,8 @@ +namespace Yaml.Poc.Tests; + +using RepoM.Core.Plugin.RepositoryOrdering; + +public class IsPinnedScorerConfigurationV1 : IRepoScorerConfiguration +{ + public int Weight { get; set; } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs new file mode 100644 index 00000000..c5527e18 --- /dev/null +++ b/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs @@ -0,0 +1,8 @@ +namespace Yaml.Poc.Tests; + +using RepoM.Core.Plugin.RepositoryOrdering; + +public class ScoreComparerConfigurationV1 : ICompareReposConfiguration +{ + public IRepoScorerConfiguration? ScoreProvider { get; set; } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs new file mode 100644 index 00000000..0e513bce --- /dev/null +++ b/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs @@ -0,0 +1,9 @@ +namespace Yaml.Poc.Tests; + +using System.Collections.Generic; +using RepoM.Core.Plugin.RepositoryOrdering; + +public class SumComparerConfigurationV1 : ICompareReposConfiguration +{ + public List Comparers { get; set; } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj index 0a183436..f5b75f58 100644 --- a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj +++ b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj @@ -35,4 +35,8 @@ + + + + diff --git a/tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt b/tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt new file mode 100644 index 00000000..7709a59c --- /dev/null +++ b/tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt @@ -0,0 +1,16 @@ +{ + Comparers: [ + { + $type: AlphabetComparerConfigurationV1, + Property: Name, + Weight: 5 + }, + { + $type: ScoreComparerConfigurationV1, + ScoreProvider: { + $type: IsPinnedScorerConfigurationV1, + Weight: 5 + } + } + ] +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index 46de1cb4..3599e0a3 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -1,148 +1,41 @@ namespace Yaml.Poc.Tests; -using System; -using System.Collections; -using System.Collections.Generic; +using System.Threading.Tasks; +using RepoM.Core.Plugin.RepositoryOrdering; +using VerifyXunit; using Xunit; -using YamlDotNet.Core; -using YamlDotNet.Core.Events; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; -using YamlDotNet.Serialization.NodeDeserializers; -using YamlDotNet.Serialization.NodeTypeResolvers; - - -/// -/// Configuration to compare two repos -/// -public interface ICompareReposData -{ -} - -// SumCompositionComparer@1 -public class SumCompositionComparerV1Data : ICompareReposData -{ - public List Items { get; set; } -} - -// ScoreComparer@1 -public class ScoreComparerV1Data : ICompareReposData -{ - public IScoreRepoData Score { get; set; } -} - -// AlphabetComparer@1 -public class AlphabetComparerV1Data : ICompareReposData -{ - public string Property { get; set; } - - public int Weight { get; set; } -} - -/// -/// Configuration to score a single repo -/// -public interface IScoreRepoData -{ -} - -// IsPinnedScorer@1 -public class IsPinnedScorerV1Data : IScoreRepoData -{ - public int Weight { get; set; } -} - - - +[UsesVerify] public class YamlTests { //https://github.com/aaubry/YamlDotNet/wiki/Serialization.Deserializer [Fact] - public void Abc() + public async Task Abc() { - string yml1 = @" -- !contact@1 - Name: Oz-Ware - PhoneNumber: 123456789 -- !repo-score-provider@1 - Score: - - provider: isPinned@1 - weight: 5"; - - string yml = @" + var yml = @" !sum-comparer@1 - items: - - !alphabet-comparer@1 + comparers: + - !az-comparer@1 property: Name weight: 5 - !score-comparer@1 - score: + score-provider: !is-pinned-scorer@1 weight: 5 "; - var deserializer = new DeserializerBuilder() - .WithNamingConvention(HyphenatedNamingConvention.Instance) - .WithTagMapping("!score-comparer@1", typeof(ScoreComparerV1Data)) - .WithTagMapping("!alphabet-comparer@1", typeof(AlphabetComparerV1Data)) - .WithTagMapping("!is-pinned-scorer@1", typeof(IsPinnedScorerV1Data)) - - - // .WithTagMapping("!repo-score-provider@1", typeof(RepoScoreProvider)) - // .WithAttributeOverride( - // c => c.Name, - // new YamlMemberAttribute - // { - // Alias = "full_name", - // }) - // .WithTypeConverter(wrapped => - // { - // return new Coen(wrapped); - // }, - // syntax => { }) - // .WithTypeInspector(inspector => - // { - // return inspector; - // }) - // .WithNodeDeserializer( - // inner => new ValidatingNodeDeserializer(inner), - // s => s.InsteadOf() - // ) - // .WithNodeTypeResolver(inner => new SystemTypeFromTagNodeTypeResolver(inner), - // s => s.InsteadOf() - // ) - .Build(); - - var result = deserializer.Deserialize(yml); - - - - } -} - -public class SystemTypeFromTagNodeTypeResolver : INodeTypeResolver -{ - public SystemTypeFromTagNodeTypeResolver(INodeTypeResolver inner) - { - //throw new NotImplementedException(); - } + IDeserializer deserializer = new DeserializerBuilder() + .WithNamingConvention(HyphenatedNamingConvention.Instance) + .WithTagMapping("!score-comparer@1", typeof(ScoreComparerConfigurationV1)) + .WithTagMapping("!az-comparer@1", typeof(AlphabetComparerConfigurationV1)) + .WithTagMapping("!sum-comparer@1", typeof(SumComparerConfigurationV1)) + .WithTagMapping("!is-pinned-scorer@1", typeof(IsPinnedScorerConfigurationV1)) + .Build(); - public bool Resolve(NodeEvent nodeEvent, ref Type currentType) - { - if (nodeEvent.Tag.Value.StartsWith("!clr:")) - { - var netTypeName = nodeEvent.Tag.Value.Substring(5); - var type = Type.GetType(netTypeName); - if (type != null) - { - currentType = type; - return true; - } - } + var result = deserializer.Deserialize(yml); - return false; + await Verifier.Verify(result); } -} - - +} \ No newline at end of file From 240d07a9c46d1bfeb49e6e5031dfc32437a9303e Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 21 Nov 2022 20:15:40 +0100 Subject: [PATCH 04/60] wip --- .../Configuration/IRepoScorerConfiguration.cs | 8 ++++++++ .../Configuration/IRepositoriesCompareConfiguration.cs | 8 ++++++++ .../RepositoryOrdering/ICompareReposConfiguration.cs | 8 -------- .../RepositoryOrdering/IRepoScorerConfiguration.cs | 8 -------- tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs | 4 ++-- tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs | 4 ++-- tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs | 6 +++--- tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs | 6 +++--- tests/Yaml.Poc.Tests/YamlTests.cs | 4 ++-- 9 files changed, 28 insertions(+), 28 deletions(-) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepoScorerConfiguration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesCompareConfiguration.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepoScorerConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepoScorerConfiguration.cs new file mode 100644 index 00000000..117fb1ad --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepoScorerConfiguration.cs @@ -0,0 +1,8 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +/// +/// Configuration to score a single repo +/// +public interface IRepositoryScorerConfiguration +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesCompareConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesCompareConfiguration.cs new file mode 100644 index 00000000..8f95d456 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesCompareConfiguration.cs @@ -0,0 +1,8 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +/// +/// Configuration to compare two repos +/// +public interface IRepositoriesCompareConfiguration +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs deleted file mode 100644 index c3bc3504..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/ICompareReposConfiguration.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering; - -/// -/// Configuration to compare two repos -/// -public interface ICompareReposConfiguration -{ -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs deleted file mode 100644 index 01be63cb..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepoScorerConfiguration.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering; - -/// -/// Configuration to score a single repo -/// -public interface IRepoScorerConfiguration -{ -} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs index 119fa16c..d81f6a50 100644 --- a/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs +++ b/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs @@ -1,8 +1,8 @@ namespace Yaml.Poc.Tests; -using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class AlphabetComparerConfigurationV1 : ICompareReposConfiguration +public class AlphabetComparerConfigurationV1 : IRepositoriesCompareConfiguration { public string? Property { get; set; } diff --git a/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs b/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs index 0bca34f3..ba2cfe82 100644 --- a/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs +++ b/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs @@ -1,8 +1,8 @@ namespace Yaml.Poc.Tests; -using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class IsPinnedScorerConfigurationV1 : IRepoScorerConfiguration +public class IsPinnedScorerConfigurationV1 : IRepositoryScorerConfiguration { public int Weight { get; set; } } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs index c5527e18..03b3bf4b 100644 --- a/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs +++ b/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs @@ -1,8 +1,8 @@ namespace Yaml.Poc.Tests; -using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class ScoreComparerConfigurationV1 : ICompareReposConfiguration +public class ScoreComparerConfigurationV1 : IRepositoriesCompareConfiguration { - public IRepoScorerConfiguration? ScoreProvider { get; set; } + public IRepositoryScorerConfiguration? ScoreProvider { get; set; } } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs index 0e513bce..eb3dc665 100644 --- a/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs +++ b/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs @@ -1,9 +1,9 @@ namespace Yaml.Poc.Tests; using System.Collections.Generic; -using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class SumComparerConfigurationV1 : ICompareReposConfiguration +public class SumComparerConfigurationV1 : IRepositoriesCompareConfiguration { - public List Comparers { get; set; } + public List Comparers { get; set; } = new(); } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index 3599e0a3..e60eddc1 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -1,7 +1,7 @@ namespace Yaml.Poc.Tests; using System.Threading.Tasks; -using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using VerifyXunit; using Xunit; using YamlDotNet.Serialization; @@ -34,7 +34,7 @@ public async Task Abc() .WithTagMapping("!is-pinned-scorer@1", typeof(IsPinnedScorerConfigurationV1)) .Build(); - var result = deserializer.Deserialize(yml); + var result = deserializer.Deserialize(yml); await Verifier.Verify(result); } From 9f04ed361ab7b6c0d42034657ef531054ea08dd5 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 21 Nov 2022 20:17:06 +0100 Subject: [PATCH 05/60] . --- ...Configuration.cs => IRepositoriesComparerConfiguration.cs} | 2 +- ...orerConfiguration.cs => IRepositoryScorerConfiguration.cs} | 0 tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs | 2 +- tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs | 2 +- tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs | 4 ++-- tests/Yaml.Poc.Tests/YamlTests.cs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/{IRepositoriesCompareConfiguration.cs => IRepositoriesComparerConfiguration.cs} (72%) rename src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/{IRepoScorerConfiguration.cs => IRepositoryScorerConfiguration.cs} (100%) diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesCompareConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesComparerConfiguration.cs similarity index 72% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesCompareConfiguration.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesComparerConfiguration.cs index 8f95d456..c1cddcba 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesCompareConfiguration.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoriesComparerConfiguration.cs @@ -3,6 +3,6 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Configuration; /// /// Configuration to compare two repos /// -public interface IRepositoriesCompareConfiguration +public interface IRepositoriesComparerConfiguration { } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepoScorerConfiguration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoryScorerConfiguration.cs similarity index 100% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepoScorerConfiguration.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IRepositoryScorerConfiguration.cs diff --git a/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs index d81f6a50..bd0fb65b 100644 --- a/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs +++ b/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs @@ -2,7 +2,7 @@ namespace Yaml.Poc.Tests; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class AlphabetComparerConfigurationV1 : IRepositoriesCompareConfiguration +public class AlphabetComparerConfigurationV1 : IRepositoriesComparerConfiguration { public string? Property { get; set; } diff --git a/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs index 03b3bf4b..c11da865 100644 --- a/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs +++ b/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs @@ -2,7 +2,7 @@ namespace Yaml.Poc.Tests; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class ScoreComparerConfigurationV1 : IRepositoriesCompareConfiguration +public class ScoreComparerConfigurationV1 : IRepositoriesComparerConfiguration { public IRepositoryScorerConfiguration? ScoreProvider { get; set; } } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs b/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs index eb3dc665..387d9482 100644 --- a/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs +++ b/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs @@ -3,7 +3,7 @@ namespace Yaml.Poc.Tests; using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class SumComparerConfigurationV1 : IRepositoriesCompareConfiguration +public class SumComparerConfigurationV1 : IRepositoriesComparerConfiguration { - public List Comparers { get; set; } = new(); + public List Comparers { get; set; } = new(); } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index e60eddc1..bd084d87 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -34,7 +34,7 @@ public async Task Abc() .WithTagMapping("!is-pinned-scorer@1", typeof(IsPinnedScorerConfigurationV1)) .Build(); - var result = deserializer.Deserialize(yml); + var result = deserializer.Deserialize(yml); await Verifier.Verify(result); } From d9f3ec4eade84df133ddd7183173b136c59c4aad Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 15:41:49 +0100 Subject: [PATCH 06/60] update --- .../IRepositoryComparerFactory.cs | 1 + .../IRepositoryScoreCalculatorFactory.cs | 20 +++++++++++++++++++ .../AlphabetComparerConfigurationV1.cs | 2 +- .../IsPinnedScorerConfigurationV1.cs | 2 +- .../ScoreComparerConfigurationV1.cs | 2 +- .../SumComparerConfigurationV1.cs | 2 +- tests/Yaml.Poc.Tests/YamlTests.cs | 1 + 7 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs rename {tests/Yaml.Poc.Tests => src/RepoM.Core.Plugin/RepositoryOrdering/Implementations}/AlphabetComparerConfigurationV1.cs (77%) rename {tests/Yaml.Poc.Tests => src/RepoM.Core.Plugin/RepositoryOrdering/Implementations}/IsPinnedScorerConfigurationV1.cs (73%) rename {tests/Yaml.Poc.Tests => src/RepoM.Core.Plugin/RepositoryOrdering/Implementations}/ScoreComparerConfigurationV1.cs (76%) rename {tests/Yaml.Poc.Tests => src/RepoM.Core.Plugin/RepositoryOrdering/Implementations}/SumComparerConfigurationV1.cs (80%) diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs index 696d9796..4bb7268f 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs @@ -2,4 +2,5 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; public interface IRepositoryComparerFactory { + IRepositoryComparer Create(); } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs new file mode 100644 index 00000000..af788702 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs @@ -0,0 +1,20 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations; + +public interface IRepositoryScoreCalculatorFactory + where TImplementation : class, IRepositoryScoreCalculator + where TConfig : IRepositoryScorerConfiguration +{ + TImplementation Create(TConfig config); +} + +public class IsPinnedScorerFactory : IRepositoryScoreCalculatorFactory +{ + public IsPinnedScoreCalculator Create(IsPinnedScorerConfigurationV1 config) + { + return new IsPinnedScoreCalculator(config.Weight); + } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AlphabetComparerConfigurationV1.cs similarity index 77% rename from tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AlphabetComparerConfigurationV1.cs index bd0fb65b..5d63fe45 100644 --- a/tests/Yaml.Poc.Tests/AlphabetComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AlphabetComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace Yaml.Poc.Tests; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScorerConfigurationV1.cs similarity index 73% rename from tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScorerConfigurationV1.cs index ba2cfe82..34f9b6bb 100644 --- a/tests/Yaml.Poc.Tests/IsPinnedScorerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScorerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace Yaml.Poc.Tests; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparerConfigurationV1.cs similarity index 76% rename from tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparerConfigurationV1.cs index c11da865..53d69c43 100644 --- a/tests/Yaml.Poc.Tests/ScoreComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace Yaml.Poc.Tests; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumComparerConfigurationV1.cs similarity index 80% rename from tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumComparerConfigurationV1.cs index 387d9482..169aca6e 100644 --- a/tests/Yaml.Poc.Tests/SumComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace Yaml.Poc.Tests; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index bd084d87..ae10f440 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -2,6 +2,7 @@ namespace Yaml.Poc.Tests; using System.Threading.Tasks; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations; using VerifyXunit; using Xunit; using YamlDotNet.Serialization; From 34c8d1906226f744b1ccc442379fd5da8d3d9a1f Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 15:44:02 +0100 Subject: [PATCH 07/60] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47e686c2..47f1ef45 100644 --- a/README.md +++ b/README.md @@ -34,4 +34,4 @@ As an extra goodie for Windows users, RepoZ automatically detects open File Expl ## Credits -RepoM is a fork of the amazing RepoZ, which was created by [Screenshot](https://github.com/awaescher/RepoZ). +RepoM is a fork of the amazing RepoZ, which was created by [Andreas Wäscher](https://github.com/awaescher/RepoZ). From 64eac7f53e07e2d5a811446ca85acc473b919c42 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 15:45:58 +0100 Subject: [PATCH 08/60] update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 47f1ef45..05601667 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ RepoM is a minimal-conf git repository hub with Windows Explorer enhancements. I It's populating itself as you work with git. It does not get in the way and does not require any user attention to work. -Repo< will not compete with your favourite git clients, so keep them. It's not about working within a repository: It's a new way to use all of your repositories to make your daily work easier. +RepoM will not compete with your favourite git clients, so keep them. It's not about working within a repository: It's a new way to use all of your repositories to make your daily work easier. 📦 [Check the Releases page](https://github.com/coenm/RepoM/releases) to **download** the latest version and see **what's new**! @@ -26,7 +26,7 @@ For Windows, use the hotkeys Ctrl+Alt+R to show To open a file browser, simply press Return on the keyboard once you selected a repository. To open a command prompt instead, hold Ctrl on Windows or Command on macOS while pressing Return. These modifier keys will also work with mouse navigation. -## Enhanced Windows Explorer Titles +## Plugin: Enhanced Windows Explorer Titles As an extra goodie for Windows users, RepoZ automatically detects open File Explorer windows and adds a status appendix to their title if they are in context of a git repository. From 587359106fd2d1cb99a387b9ad98862f76e621ff Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 17:16:14 +0100 Subject: [PATCH 09/60] wip --- tests/Yaml.Poc.Tests/DI/Class1.cs | 65 +++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/Yaml.Poc.Tests/DI/Class1.cs diff --git a/tests/Yaml.Poc.Tests/DI/Class1.cs b/tests/Yaml.Poc.Tests/DI/Class1.cs new file mode 100644 index 00000000..09fd2bc3 --- /dev/null +++ b/tests/Yaml.Poc.Tests/DI/Class1.cs @@ -0,0 +1,65 @@ +namespace Yaml.Poc.Tests.DI; + +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using System.Threading; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using SimpleInjector; + +public interface IQueryHandler where T1: IQuery +{ + +} +public interface IQuery +{ + +} + +[DebuggerDisplay("{QueryType.Name,nq}")] +public sealed class QueryInfo +{ + public QueryInfo(Type queryType) + { + QueryType = queryType; + ResultType = DetermineResultTypes(queryType).Single(); + } + + public Type QueryType { get; } + + public Type ResultType { get; } + + public static bool IsQuery(Type type) + { + return DetermineResultTypes(type).Any(); + } + + private static IEnumerable DetermineResultTypes(Type type) + { + return from interfaceType in type.GetInterfaces() + where interfaceType.IsGenericType + where interfaceType.GetGenericTypeDefinition() == typeof(IQuery<>) + select interfaceType.GetGenericArguments()[0]; + } +} + +public class QueryProcessor +{ + private readonly Container _container; + + public QueryProcessor(Container container) + { + this._container = container; + } + + public async Task ExecuteQueryAsync(IQuery query, CancellationToken ct = default) + { + Type handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult)); + + dynamic handler = _container.GetInstance(handlerType); + + return await handler.HandleAsync((dynamic)query, null, ct); + } +} \ No newline at end of file From 09e53f1130b4face225c7aff4338dd36d0775a7b Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 17:44:27 +0100 Subject: [PATCH 10/60] updadte --- tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj index f5b75f58..c17a6b5f 100644 --- a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj +++ b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj @@ -19,6 +19,7 @@ + From 8682f2f2de60eb3e85a1074af8f91aef023a0169 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 21:07:41 +0100 Subject: [PATCH 11/60] cleanup --- .../IRepositoryComparerFactory.cs | 7 +++- .../IRepositoryScoreCalculatorFactory.cs | 15 +------- .../AlphabetComparerConfigurationV1.cs | 2 +- .../Implementations/{ => Az}/AzComparer.cs | 2 +- .../Az/AzRepositoryComparerFactory.cs | 9 +++++ .../{ => Composition}/CompositionComparer.cs | 2 +- .../CompositionComparerConfigurationV1.cs | 9 +++++ .../CompositionRepositoryComparerFactory.cs | 12 ++++++ .../{ => IsPinned}/IsPinnedScoreCalculator.cs | 2 +- .../IsPinnedScorerConfigurationV1.cs | 2 +- .../IsPinned/IsPinnedScorerFactory.cs | 9 +++++ .../Implementations/IsPinnedComparer.cs | 38 ------------------- .../Label/LabelScoreCalculator.cs | 16 ++++++++ .../Label/LabelScorerConfigurationV1.cs | 10 +++++ .../Label/LabelScorerFactory.cs | 9 +++++ .../{ => Score}/ScoreComparer.cs | 2 +- .../ScoreComparerConfigurationV1.cs | 3 +- .../Score/ScoreRepositoryComparerFactory.cs | 14 +++++++ .../{ => Sum}/SumComparerConfigurationV1.cs | 2 +- .../{ => Sum}/SumCompositionComparer.cs | 2 +- .../Sum/SumRepositoryComparerFactory.cs | 12 ++++++ tests/Yaml.Poc.Tests/DI/Class1.cs | 9 +---- tests/Yaml.Poc.Tests/YamlTests.cs | 5 ++- 23 files changed, 123 insertions(+), 70 deletions(-) rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => Az}/AlphabetComparerConfigurationV1.cs (76%) rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => Az}/AzComparer.cs (95%) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => Composition}/CompositionComparer.cs (90%) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => IsPinned}/IsPinnedScoreCalculator.cs (80%) rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => IsPinned}/IsPinnedScorerConfigurationV1.cs (70%) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => Score}/ScoreComparer.cs (90%) rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => Score}/ScoreComparerConfigurationV1.cs (61%) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => Sum}/SumComparerConfigurationV1.cs (79%) rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/{ => Sum}/SumCompositionComparer.cs (90%) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs index 4bb7268f..b9e346fd 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs @@ -1,6 +1,9 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; -public interface IRepositoryComparerFactory +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public interface IRepositoryComparerFactory + where TConfig : IRepositoriesComparerConfiguration { - IRepositoryComparer Create(); + IRepositoryComparer Create(TConfig configuration); } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs index af788702..3cd044e7 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs @@ -1,20 +1,9 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; -using System; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations; -public interface IRepositoryScoreCalculatorFactory - where TImplementation : class, IRepositoryScoreCalculator +public interface IRepositoryScoreCalculatorFactory where TConfig : IRepositoryScorerConfiguration { - TImplementation Create(TConfig config); -} - -public class IsPinnedScorerFactory : IRepositoryScoreCalculatorFactory -{ - public IsPinnedScoreCalculator Create(IsPinnedScorerConfigurationV1 config) - { - return new IsPinnedScoreCalculator(config.Weight); - } + IRepositoryScoreCalculator Create(TConfig config); } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AlphabetComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1.cs similarity index 76% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AlphabetComparerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1.cs index 5d63fe45..4253396c 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AlphabetComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AzComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs similarity index 95% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AzComparer.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs index 6b41bd73..048f6bed 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/AzComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; using System; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs new file mode 100644 index 00000000..9140cc50 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs @@ -0,0 +1,9 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; + +public class AzRepositoryComparerFactory : IRepositoryComparerFactory +{ + public IRepositoryComparer Create(AlphabetComparerConfigurationV1 configuration) + { + return new AzComparer(); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/CompositionComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparer.cs similarity index 90% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/CompositionComparer.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparer.cs index 347aed51..a10e9248 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/CompositionComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparer.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; using System.Collections.Generic; using System.Linq; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1.cs new file mode 100644 index 00000000..c5cb49c7 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1.cs @@ -0,0 +1,9 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; + +using System.Collections.Generic; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class CompositionComparerConfigurationV1 : IRepositoriesComparerConfiguration +{ + public List Comparers { get; set; } = new(); +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs new file mode 100644 index 00000000..4eff69fc --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs @@ -0,0 +1,12 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; + +using System.Collections.Generic; + +public class CompositionRepositoryComparerFactory : IRepositoryComparerFactory +{ + public IRepositoryComparer Create(CompositionComparerConfigurationV1 configuration) + { + // configuration.ScoreProvider + return new CompositionComparer(new List()); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScoreCalculator.cs similarity index 80% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScoreCalculator.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScoreCalculator.cs index e81635c5..34a00c7a 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScoreCalculator.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScoreCalculator.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; public class IsPinnedScoreCalculator : IRepositoryScoreCalculator { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScorerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs similarity index 70% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScorerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs index 34f9b6bb..4a4b3a02 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedScorerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs new file mode 100644 index 00000000..1a1dbf9c --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs @@ -0,0 +1,9 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; + +public class IsPinnedScorerFactory : IRepositoryScoreCalculatorFactory +{ + public IRepositoryScoreCalculator Create(IsPinnedScorerConfigurationV1 config) + { + return new IsPinnedScoreCalculator(config.Weight); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs deleted file mode 100644 index 6f395cea..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinnedComparer.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; - -using System; - -public class IsPinnedComparer : IRepositoryComparer -{ - private readonly int _weight; - - public IsPinnedComparer(int weight) - { - if (weight <= 0) - { - throw new ArgumentOutOfRangeException(nameof(weight), "Should be positive"); - } - - _weight = weight; - } - - public int Compare(IPluginRepository x, IPluginRepository y) - { - if (ReferenceEquals(x, y)) - { - return 0; - } - - if (ReferenceEquals(null, y)) - { - return 1; - } - - if (ReferenceEquals(null, x)) - { - return -1; - } - - return x.IsPinned.CompareTo(y.IsPinned) * _weight; - } -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs new file mode 100644 index 00000000..01f5b33b --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs @@ -0,0 +1,16 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; + +public class LabelScoreCalculator : IRepositoryScoreCalculator +{ + private readonly int _weight; + + public LabelScoreCalculator(int weight) + { + _weight = weight; + } + + public int Score(IPluginRepository repository) + { + return 0; + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs new file mode 100644 index 00000000..0ed157f0 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs @@ -0,0 +1,10 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; + +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class LabelScorerConfigurationV1 : IRepositoryScorerConfiguration +{ + public int Weight { get; set; } + + public string? Label { get; set; } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs new file mode 100644 index 00000000..343132f0 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs @@ -0,0 +1,9 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; + +public class LabelScorerFactory : IRepositoryScoreCalculatorFactory +{ + public IRepositoryScoreCalculator Create(LabelScorerConfigurationV1 config) + { + return new LabelScoreCalculator(config.Weight); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs similarity index 90% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparer.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs index 04e924ca..a7b30957 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using System; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs similarity index 61% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs index 53d69c43..3636c470 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/ScoreComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs @@ -1,6 +1,7 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; public class ScoreComparerConfigurationV1 : IRepositoriesComparerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs new file mode 100644 index 00000000..942ba828 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs @@ -0,0 +1,14 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; + +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; + +public class ScoreRepositoryComparerFactory : IRepositoryComparerFactory +{ + public IRepositoryComparer Create(ScoreComparerConfigurationV1 configuration) + { + // configuration.ScoreProvider + + IRepositoryScoreCalculator calculator = new IsPinnedScoreCalculator(2); + return new ScoreComparer(calculator); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs similarity index 79% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumComparerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs index 169aca6e..297c48d9 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumCompositionComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs similarity index 90% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumCompositionComparer.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs index 97f5d8b5..a516792f 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/SumCompositionComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using System.Collections.Generic; using System.Linq; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs new file mode 100644 index 00000000..91e365c2 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs @@ -0,0 +1,12 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; + +using System.Collections.Generic; + +public class SumRepositoryComparerFactory : IRepositoryComparerFactory +{ + public IRepositoryComparer Create(SumComparerConfigurationV1 configuration) + { + // configuration.ScoreProvider + return new SumCompositionComparer(new List()); + } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/DI/Class1.cs b/tests/Yaml.Poc.Tests/DI/Class1.cs index 09fd2bc3..7dc13119 100644 --- a/tests/Yaml.Poc.Tests/DI/Class1.cs +++ b/tests/Yaml.Poc.Tests/DI/Class1.cs @@ -7,15 +7,10 @@ namespace Yaml.Poc.Tests.DI; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using RepoM.Core.Plugin.RepositoryOrdering; using SimpleInjector; - -public interface IQueryHandler where T1: IQuery -{ - -} public interface IQuery { - } [DebuggerDisplay("{QueryType.Name,nq}")] @@ -56,7 +51,7 @@ public QueryProcessor(Container container) public async Task ExecuteQueryAsync(IQuery query, CancellationToken ct = default) { - Type handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult)); + Type handlerType = typeof(IRepositoryScoreCalculatorFactory<>).MakeGenericType(query.GetType()); dynamic handler = _container.GetInstance(handlerType); diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index ae10f440..1b28eae6 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -2,7 +2,10 @@ namespace Yaml.Poc.Tests; using System.Threading.Tasks; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using VerifyXunit; using Xunit; using YamlDotNet.Serialization; From fc1e9f8c0c900e40c726a85dc615e8c6e6c67ccf Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 21:28:08 +0100 Subject: [PATCH 12/60] update --- .../Configuration/IConfigurationRegistration.cs | 13 +++++++++++++ .../AlphabetComparerConfigurationV1Registration.cs | 11 +++++++++++ ...ompositionComparerConfigurationV1Registration.cs | 11 +++++++++++ .../IsPinned/IsPinnedScorerConfigurationV1.cs | 1 + .../IsPinnedScorerConfigurationV1Registration.cs | 11 +++++++++++ .../Implementations/Label/LabelScoreCalculator.cs | 2 +- .../Label/LabelScorerConfigurationV1.cs | 1 + .../Label/LabelScorerConfigurationV1Registration.cs | 11 +++++++++++ .../Score/ScoreComparerConfigurationV1.cs | 1 - .../ScoreComparerConfigurationV1Registration.cs | 11 +++++++++++ .../Sum/SumComparerConfigurationV1.cs | 1 + .../Sum/SumComparerConfigurationV1Registration.cs | 11 +++++++++++ 12 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IConfigurationRegistration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1Registration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IConfigurationRegistration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IConfigurationRegistration.cs new file mode 100644 index 00000000..93ec4a4b --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Configuration/IConfigurationRegistration.cs @@ -0,0 +1,13 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +using System; + +/// +/// Configuration registration per name +/// +public interface IConfigurationRegistration +{ + public Type ConfigurationType { get; } + + public string Tag { get; } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1Registration.cs new file mode 100644 index 00000000..e834ccbc --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1Registration.cs @@ -0,0 +1,11 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class AlphabetComparerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(AlphabetComparerConfigurationV1); + + public string Tag { get; } = "az-comparer@1"; +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs new file mode 100644 index 00000000..ff95f606 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs @@ -0,0 +1,11 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class CompositionComparerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(CompositionComparerConfigurationV1); + + public string Tag { get; } = "xx@1"; +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs index 4a4b3a02..57ff5108 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs @@ -1,6 +1,7 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; public class IsPinnedScorerConfigurationV1 : IRepositoryScorerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs new file mode 100644 index 00000000..7f040a3e --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs @@ -0,0 +1,11 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class IsPinnedScorerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(IsPinnedScorerConfigurationV1); + + public string Tag { get; } = "is-pinned@1"; +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs index 01f5b33b..f2ac5125 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; public class LabelScoreCalculator : IRepositoryScoreCalculator { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs index 0ed157f0..72b69a2a 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs @@ -1,6 +1,7 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; public class LabelScorerConfigurationV1 : IRepositoryScorerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs new file mode 100644 index 00000000..b8ac7118 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs @@ -0,0 +1,11 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class LabelScorerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(LabelScorerConfigurationV1); + + public string Tag { get; } = "label@1"; +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs index 3636c470..3df86a41 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs @@ -1,7 +1,6 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; public class ScoreComparerConfigurationV1 : IRepositoriesComparerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs new file mode 100644 index 00000000..1b5f732c --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs @@ -0,0 +1,11 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class ScoreComparerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(ScoreComparerConfigurationV1); + + public string Tag { get; } = "score@1"; +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs index 297c48d9..e39a4d5a 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs @@ -2,6 +2,7 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; public class SumComparerConfigurationV1 : IRepositoriesComparerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs new file mode 100644 index 00000000..72f997c3 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs @@ -0,0 +1,11 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class SumComparerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(SumComparerConfigurationV1); + + public string Tag { get; } = "sum@1"; +} \ No newline at end of file From 6dfdb5d76a5dbdd049ba4fa6090319b17101916f Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 22 Nov 2022 21:53:33 +0100 Subject: [PATCH 13/60] .. --- ...tionComparerConfigurationV1Registration.cs | 2 +- ...PinnedScorerConfigurationV1Registration.cs | 2 +- .../LabelScorerConfigurationV1Registration.cs | 2 +- ...coreComparerConfigurationV1Registration.cs | 4 +- .../SumComparerConfigurationV1Registration.cs | 2 +- tests/Yaml.Poc.Tests/DI/Bootstrapper.cs | 36 ++++++++++++++++ tests/Yaml.Poc.Tests/YamlTests.cs | 41 ++++++++++++++++--- 7 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 tests/Yaml.Poc.Tests/DI/Bootstrapper.cs diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs index ff95f606..10cdd316 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class CompositionComparerConfigurationV1Registration : IConfigurationRegi { public Type ConfigurationType { get; } = typeof(CompositionComparerConfigurationV1); - public string Tag { get; } = "xx@1"; + public string Tag { get; } = "composition@1"; } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs index 7f040a3e..842eb016 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class IsPinnedScorerConfigurationV1Registration : IConfigurationRegistrat { public Type ConfigurationType { get; } = typeof(IsPinnedScorerConfigurationV1); - public string Tag { get; } = "is-pinned@1"; + public string Tag { get; } = "is-pinned-scorer@1"; } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs index b8ac7118..d5d5f66c 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class LabelScorerConfigurationV1Registration : IConfigurationRegistration { public Type ConfigurationType { get; } = typeof(LabelScorerConfigurationV1); - public string Tag { get; } = "label@1"; + public string Tag { get; } = "label-scorer@1"; } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs index 1b5f732c..c82c15b5 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class ScoreComparerConfigurationV1Registration : IConfigurationRegistrati { public Type ConfigurationType { get; } = typeof(ScoreComparerConfigurationV1); - public string Tag { get; } = "score@1"; -} \ No newline at end of file + public string Tag { get; } = "score-comparer@1"; +} diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs index 72f997c3..df2f74a2 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class SumComparerConfigurationV1Registration : IConfigurationRegistration { public Type ConfigurationType { get; } = typeof(SumComparerConfigurationV1); - public string Tag { get; } = "sum@1"; + public string Tag { get; } = "sum-comparer@1"; } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs new file mode 100644 index 00000000..688ee735 --- /dev/null +++ b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs @@ -0,0 +1,36 @@ +namespace Yaml.Poc.Tests.DI; + +using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; +using SimpleInjector; +using Container = SimpleInjector.Container; + +internal static class Bootstrapper +{ + public static void RegisterOrderingConfiguration(Container container) + { + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); + + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); + + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, LabelScorerFactory>(Lifestyle.Singleton); + + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); + + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, SumRepositoryComparerFactory>(Lifestyle.Singleton); + } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index 1b28eae6..1831b31d 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -1,24 +1,25 @@ namespace Yaml.Poc.Tests; +using System.Collections.Generic; using System.Threading.Tasks; +using FakeItEasy; +using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; +using SimpleInjector; using VerifyXunit; using Xunit; +using Yaml.Poc.Tests.DI; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [UsesVerify] public class YamlTests { - //https://github.com/aaubry/YamlDotNet/wiki/Serialization.Deserializer - [Fact] - public async Task Abc() - { - var yml = @" + private readonly string yml = @" !sum-comparer@1 comparers: - !az-comparer@1 @@ -30,6 +31,10 @@ public async Task Abc() weight: 5 "; + //https://github.com/aaubry/YamlDotNet/wiki/Serialization.Deserializer + [Fact] + public async Task Abc() + { IDeserializer deserializer = new DeserializerBuilder() .WithNamingConvention(HyphenatedNamingConvention.Instance) .WithTagMapping("!score-comparer@1", typeof(ScoreComparerConfigurationV1)) @@ -42,4 +47,30 @@ public async Task Abc() await Verifier.Verify(result); } + + + [Fact] + public async Task DI() + { + var container = new Container(); + Bootstrapper.RegisterOrderingConfiguration(container); + container.Verify(); + + DeserializerBuilder builder = new DeserializerBuilder() + .WithNamingConvention(HyphenatedNamingConvention.Instance); + + foreach (IConfigurationRegistration instance in container.GetAllInstances()) + { + var tag = instance.Tag.TrimStart('!'); + builder.WithTagMapping("!" + tag, instance.ConfigurationType); + } + + IDeserializer deserializer = builder.Build(); + + + IRepositoriesComparerConfiguration result = deserializer.Deserialize(yml); + // var instance2s = container.GetAllInstances>(); + // IRepositoryComparerFactory + await Verifier.Verify(result).UseMethodName(nameof(Abc)); + } } \ No newline at end of file From ecb628c491b692d4eb93d929345905ee342fcd73 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Thu, 24 Nov 2022 22:08:43 +0100 Subject: [PATCH 14/60] update --- .../Git/AutoFetch/DefaultAutoFetchHandler.cs | 10 +- .../DefaultRepositoryInformationAggregator.cs | 16 ++-- .../Git/IRepositoryInformationAggregator.cs | 2 +- src/RepoM.Api/Git/IRepositoryView.cs | 2 + src/RepoM.Api/Git/Repository.cs | 3 +- ...positoryView.cs => RepositoryViewModel.cs} | 7 +- .../IsPinned/IsPinnedScoreCalculator.cs | 28 ++++++ .../IsPinned/IsPinnedScorerConfigurationV1.cs | 3 +- ...PinnedScorerConfigurationV1Registration.cs | 4 +- .../IsPinned/IsPinnedScorerFactory.cs | 20 ++++ src/RepoM.Api/RepoM.Api.csproj | 6 ++ .../CustomRepositoryViewSortComparer.cs | 28 ------ src/RepoM.App/MainWindow.xaml.cs | 31 +++++-- src/RepoM.App/RepositoryComparerAdapter.cs | 31 +++++++ src/RepoM.Core.Plugin/IRepository.cs | 20 ++++ .../RepositoryOrdering/IPluginRepository.cs | 14 --- .../RepositoryOrdering/IRepositoryComparer.cs | 2 +- .../IRepositoryComparerFactory.cs | 5 + .../IRepositoryScoreCalculator.cs | 2 +- .../IRepositoryScoreCalculatorFactory.cs | 5 + .../Implementations/Az/AzComparer.cs | 55 +++++------ .../Az/AzRepositoryComparerFactory.cs | 2 +- .../Composition/CompositionComparer.cs | 2 +- .../CompositionRepositoryComparerFactory.cs | 13 ++- .../IsPinned/IsPinnedScoreCalculator.cs | 16 ---- .../IsPinned/IsPinnedScorerFactory.cs | 9 -- .../Label/LabelScoreCalculator.cs | 10 +- .../Label/LabelScorerConfigurationV1.cs | 1 - .../Label/LabelScorerFactory.cs | 9 +- .../Implementations/Score/ScoreComparer.cs | 5 +- .../Score/ScoreRepositoryComparerFactory.cs | 14 ++- .../Sum/SumComparerConfigurationV1.cs | 1 - .../Sum/SumCompositionComparer.cs | 2 +- .../Sum/SumRepositoryComparerFactory.cs | 13 ++- tests/Tests/UI/RepositoryViewTests.cs | 86 ++++++++--------- tests/Yaml.Poc.Tests/DI/Bootstrapper.cs | 93 ++++++++++++++++++- tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj | 1 + .../Yaml.Poc.Tests/YamlTests.DI.verified.txt | 16 ++++ tests/Yaml.Poc.Tests/YamlTests.cs | 50 ++++++++-- 39 files changed, 434 insertions(+), 203 deletions(-) rename src/RepoM.Api/Git/{RepositoryView.cs => RepositoryViewModel.cs} (95%) create mode 100644 src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/IsPinned/IsPinnedScorerConfigurationV1.cs (54%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/IsPinned/IsPinnedScorerConfigurationV1Registration.cs (77%) create mode 100644 src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerFactory.cs delete mode 100644 src/RepoM.App/CustomRepositoryViewSortComparer.cs create mode 100644 src/RepoM.App/RepositoryComparerAdapter.cs create mode 100644 src/RepoM.Core.Plugin/IRepository.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScoreCalculator.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs create mode 100644 tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt diff --git a/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs b/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs index 799bc92d..d393c70b 100644 --- a/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs +++ b/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs @@ -85,14 +85,14 @@ private void FetchNext(object timerState) _lastFetchRepository = 0; } - RepositoryView repositoryView = repositories[_lastFetchRepository]; + RepositoryViewModel repositoryViewModel = repositories[_lastFetchRepository]; - Console.WriteLine($"Auto-fetching {repositoryView.Name} (index {_lastFetchRepository} of {repositories.Count})"); + Console.WriteLine($"Auto-fetching {repositoryViewModel.Name} (index {_lastFetchRepository} of {repositories.Count})"); - repositoryView.IsSynchronizing = true; + repositoryViewModel.IsSynchronizing = true; try { - RepositoryWriter.Fetch(repositoryView.Repository); + RepositoryWriter.Fetch(repositoryViewModel.Repository); } catch { @@ -103,7 +103,7 @@ private void FetchNext(object timerState) // re-enable the timer to get to the next fetch UpdateBehavior(); - repositoryView.IsSynchronizing = false; + repositoryViewModel.IsSynchronizing = false; } } diff --git a/src/RepoM.Api/Git/DefaultRepositoryInformationAggregator.cs b/src/RepoM.Api/Git/DefaultRepositoryInformationAggregator.cs index 55faa4b1..eaf497ec 100644 --- a/src/RepoM.Api/Git/DefaultRepositoryInformationAggregator.cs +++ b/src/RepoM.Api/Git/DefaultRepositoryInformationAggregator.cs @@ -13,16 +13,16 @@ public class DefaultRepositoryInformationAggregator : IRepositoryInformationAggr public DefaultRepositoryInformationAggregator(IThreadDispatcher dispatcher) { _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher)); - Repositories = new ObservableCollection(); + Repositories = new ObservableCollection(); } - public ObservableCollection Repositories { get; } + public ObservableCollection Repositories { get; } public void Add(Repository repository, IRepositoryMonitor repositoryMonitor) { _dispatcher.Invoke(() => { - var view = new RepositoryView(repository, repositoryMonitor); + var view = new RepositoryViewModel(repository, repositoryMonitor); Repositories.Remove(view); Repositories.Add(view); @@ -33,7 +33,7 @@ public void RemoveByPath(string path) { _dispatcher.Invoke(() => { - RepositoryView[] viewsToRemove = Repositories.Where(r => r.Path.Equals(path, StringComparison.OrdinalIgnoreCase)).ToArray(); + RepositoryViewModel[] viewsToRemove = Repositories.Where(r => r.Path.Equals(path, StringComparison.OrdinalIgnoreCase)).ToArray(); for (var i = viewsToRemove.Length - 1; i >= 0; i--) { @@ -44,18 +44,18 @@ public void RemoveByPath(string path) public string? GetStatusByPath(string path) { - RepositoryView? view = GetRepositoryByPath(path); + RepositoryViewModel? view = GetRepositoryByPath(path); return view?.BranchWithStatus; } - private RepositoryView? GetRepositoryByPath(string path) + private RepositoryViewModel? GetRepositoryByPath(string path) { if (string.IsNullOrEmpty(path)) { return null; } - List? views = null; + List? views = null; try { views = Repositories.ToList(); @@ -76,7 +76,7 @@ public void RemoveByPath(string path) path += "\\"; } - RepositoryView[] viewsByPath = views! + RepositoryViewModel[] viewsByPath = views! .Where(r => r?.Path != null && diff --git a/src/RepoM.Api/Git/IRepositoryInformationAggregator.cs b/src/RepoM.Api/Git/IRepositoryInformationAggregator.cs index 4d159bbc..05c0ea8b 100644 --- a/src/RepoM.Api/Git/IRepositoryInformationAggregator.cs +++ b/src/RepoM.Api/Git/IRepositoryInformationAggregator.cs @@ -10,7 +10,7 @@ public interface IRepositoryInformationAggregator string? GetStatusByPath(string path); - ObservableCollection Repositories { get; } + ObservableCollection Repositories { get; } void Reset(); diff --git a/src/RepoM.Api/Git/IRepositoryView.cs b/src/RepoM.Api/Git/IRepositoryView.cs index e5291cea..2a2fa629 100644 --- a/src/RepoM.Api/Git/IRepositoryView.cs +++ b/src/RepoM.Api/Git/IRepositoryView.cs @@ -11,4 +11,6 @@ public interface IRepositoryView bool IsPinned { get; } bool HasUnpushedChanges { get; } + + Repository Repository { get; } } \ No newline at end of file diff --git a/src/RepoM.Api/Git/Repository.cs b/src/RepoM.Api/Git/Repository.cs index bd7a0f38..398ac243 100644 --- a/src/RepoM.Api/Git/Repository.cs +++ b/src/RepoM.Api/Git/Repository.cs @@ -3,9 +3,10 @@ namespace RepoM.Api.Git; using System; using System.Collections.Generic; using System.Diagnostics; +using RepoM.Core.Plugin; [DebuggerDisplay("{Name} @{Path}")] -public class Repository +public class Repository : IRepository { public Repository() { diff --git a/src/RepoM.Api/Git/RepositoryView.cs b/src/RepoM.Api/Git/RepositoryViewModel.cs similarity index 95% rename from src/RepoM.Api/Git/RepositoryView.cs rename to src/RepoM.Api/Git/RepositoryViewModel.cs index e75284e6..1e315375 100644 --- a/src/RepoM.Api/Git/RepositoryView.cs +++ b/src/RepoM.Api/Git/RepositoryViewModel.cs @@ -6,7 +6,7 @@ namespace RepoM.Api.Git; using System.Linq; [DebuggerDisplay("{Name} @{Path}")] -public class RepositoryView : IRepositoryView, INotifyPropertyChanged +public class RepositoryViewModel : IRepositoryView, INotifyPropertyChanged { private readonly IRepositoryMonitor _monitor; private string? _cachedRepositoryStatusCode; @@ -16,7 +16,7 @@ public class RepositoryView : IRepositoryView, INotifyPropertyChanged public event PropertyChangedEventHandler? PropertyChanged; - public RepositoryView(Repository repository, IRepositoryMonitor monitor) + public RepositoryViewModel(Repository repository, IRepositoryMonitor monitor) { _monitor = monitor ?? throw new ArgumentNullException(nameof(monitor)); Repository = repository ?? throw new ArgumentNullException(nameof(repository)); @@ -25,7 +25,7 @@ public RepositoryView(Repository repository, IRepositoryMonitor monitor) public override bool Equals(object obj) { - if (obj is RepositoryView other) + if (obj is RepositoryViewModel other) { return other.Repository.Equals(Repository); } @@ -128,4 +128,5 @@ public bool IsSynchronizing private string SyncAppendix => " \u2191\u2193"; // up and down arrows public DateTime UpdateStampUtc { get; private set; } + } \ No newline at end of file diff --git a/src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs new file mode 100644 index 00000000..a45385ac --- /dev/null +++ b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs @@ -0,0 +1,28 @@ +namespace RepoM.Api.Ordering.IsPinned; + +using System; +using RepoM.Api.Git; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; + +public class IsPinnedScoreCalculator : IRepositoryScoreCalculator +{ + private readonly IRepositoryMonitor _monitor; + private readonly int _weight; + + public IsPinnedScoreCalculator(IRepositoryMonitor monitor, int weight) + { + _monitor = monitor ?? throw new ArgumentNullException(nameof(monitor)); + _weight = weight; + } + + public int Score(IRepository repository) + { + if (repository is Repository r) + { + return _monitor.IsPinned(r) ? _weight : 0; + } + + return 0; + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1.cs similarity index 54% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs rename to src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1.cs index 57ff5108..fec738a7 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1.cs +++ b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1.cs @@ -1,7 +1,6 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; +namespace RepoM.Api.Ordering.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; public class IsPinnedScorerConfigurationV1 : IRepositoryScorerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1Registration.cs similarity index 77% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs rename to src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1Registration.cs index 842eb016..52187348 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1Registration.cs @@ -1,8 +1,10 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; +namespace RepoM.Api.Ordering.IsPinned; using System; +using JetBrains.Annotations; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +[UsedImplicitly] public class IsPinnedScorerConfigurationV1Registration : IConfigurationRegistration { public Type ConfigurationType { get; } = typeof(IsPinnedScorerConfigurationV1); diff --git a/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerFactory.cs b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerFactory.cs new file mode 100644 index 00000000..60fb827c --- /dev/null +++ b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerFactory.cs @@ -0,0 +1,20 @@ +namespace RepoM.Api.Ordering.IsPinned; + +using System; +using RepoM.Api.Git; +using RepoM.Core.Plugin.RepositoryOrdering; + +public class IsPinnedScorerFactory : IRepositoryScoreCalculatorFactory +{ + private readonly IRepositoryMonitor _monitor; + + public IsPinnedScorerFactory(IRepositoryMonitor monitor) + { + _monitor = monitor ?? throw new ArgumentNullException(nameof(monitor)); + } + + public IRepositoryScoreCalculator Create(IsPinnedScorerConfigurationV1 config) + { + return new IsPinnedScoreCalculator(_monitor, config.Weight); + } +} \ No newline at end of file diff --git a/src/RepoM.Api/RepoM.Api.csproj b/src/RepoM.Api/RepoM.Api.csproj index ec7e36fe..32bcf80a 100644 --- a/src/RepoM.Api/RepoM.Api.csproj +++ b/src/RepoM.Api/RepoM.Api.csproj @@ -12,4 +12,10 @@ + + + + + + diff --git a/src/RepoM.App/CustomRepositoryViewSortComparer.cs b/src/RepoM.App/CustomRepositoryViewSortComparer.cs deleted file mode 100644 index 426a6b2b..00000000 --- a/src/RepoM.App/CustomRepositoryViewSortComparer.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace RepoM.App; - -using System.Collections; -using RepoM.Api.Git; - -internal class CustomRepositoryViewSortComparer : IComparer -{ - public int Compare(object? x, object? y) - { - if (x is IRepositoryView xView && y is IRepositoryView yView) - { - return Compare(xView, yView); - } - - return 0; - } - - private static int Compare(IRepositoryView x, IRepositoryView y) - { - if (x.IsPinned == y.IsPinned) - { - return string.CompareOrdinal(x.Name, y.Name); - } - - // pinned should be first ;-) - return x.IsPinned ? -1 : 1; - } -} \ No newline at end of file diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index 7e1cb686..c2d3e0d8 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -17,8 +17,15 @@ namespace RepoM.App; using RepoM.Api.Common; using RepoM.Api.Git; using RepoM.Api.IO; +using RepoM.Api.Ordering.IsPinned; using RepoM.App.Controls; using RepoM.App.Services; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using SourceChord.FluentWPF; /// @@ -75,7 +82,15 @@ public MainWindow( var view = (ListCollectionView)CollectionViewSource.GetDefaultView(aggregator.Repositories); ((ICollectionView)view).CollectionChanged += View_CollectionChanged; view.Filter = FilterRepositories; - view.CustomSort = new CustomRepositoryViewSortComparer(); + view.CustomSort = new RepositoryComparerAdapter( + new CompositionComparer( + new IRepositoryComparer[] + { + new ScoreComparer(new IsPinnedScoreCalculator(repositoryMonitor, 1)), + // new ScoreComparer(new LabelScoreCalculator("Prive", 1)), + new AzComparer(1, nameof(IRepository.Name)), + } + )); AssemblyName? appName = Assembly.GetEntryAssembly()?.GetName(); txtHelpCaption.Text = appName?.Name + " " + appName?.Version?.ToString(2); @@ -87,7 +102,7 @@ public MainWindow( private void View_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { // use the list's itemsource directly, this one is not filtered (otherwise searching in the UI without matches could lead to the "no repositories yet"-screen) - var hasRepositories = lstRepositories.ItemsSource.OfType().Any(); + var hasRepositories = lstRepositories.ItemsSource.OfType().Any(); tbNoRepositories.Visibility = hasRepositories ? Visibility.Hidden : Visibility.Visible; } @@ -178,7 +193,7 @@ private void LstRepositories_ContextMenuOpening(object? sender, ContextMenuEvent private bool LstRepositoriesContextMenuOpening(object sender, ContextMenu ctxMenu) { - RepositoryView[] selectedViews = lstRepositories.SelectedItems.OfType().ToArray(); + RepositoryViewModel[] selectedViews = lstRepositories.SelectedItems.OfType().ToArray(); if (!selectedViews.Any()) { @@ -243,7 +258,7 @@ private void LstRepositories_KeyDown(object? sender, KeyEventArgs e) private void InvokeActionOnCurrentRepository() { - if (lstRepositories.SelectedItem is not RepositoryView selectedView) + if (lstRepositories.SelectedItem is not RepositoryViewModel selectedView) { return; } @@ -380,7 +395,7 @@ private void ShowUpdateIfAvailable() parent.ColumnDefinitions[Grid.GetColumn(UpdateButton)].Width = App.AvailableUpdate == null ? new GridLength(0) : GridLength.Auto; } - private static Control? /*MenuItem*/ CreateMenuItem(object sender, RepositoryActionBase action, IEnumerable? affectedViews = null) + private static Control? /*MenuItem*/ CreateMenuItem(object sender, RepositoryActionBase action, IEnumerable? affectedViews = null) { if (action is RepositorySeparatorAction) { @@ -465,14 +480,14 @@ void SelfDetachingEventHandler(object _, RoutedEventArgs evtArgs) return item; } - private static void SetViewsSynchronizing(IEnumerable? affectedViews, bool synchronizing) + private static void SetViewsSynchronizing(IEnumerable? affectedViews, bool synchronizing) { if (affectedViews == null) { return; } - foreach (RepositoryView view in affectedViews) + foreach (RepositoryViewModel view in affectedViews) { view.IsSynchronizing = synchronizing; } @@ -557,7 +572,7 @@ private bool FilterRepositories(object item) return false; } - if (item is not RepositoryView viewModelItem) + if (item is not RepositoryViewModel viewModelItem) { return false; } diff --git a/src/RepoM.App/RepositoryComparerAdapter.cs b/src/RepoM.App/RepositoryComparerAdapter.cs new file mode 100644 index 00000000..f6e4722e --- /dev/null +++ b/src/RepoM.App/RepositoryComparerAdapter.cs @@ -0,0 +1,31 @@ +namespace RepoM.App; + +using System; +using System.Collections; +using RepoM.Api.Git; +using RepoM.Core.Plugin.RepositoryOrdering; + +internal class RepositoryComparerAdapter : IComparer +{ + private readonly IRepositoryComparer _comparer; + + public RepositoryComparerAdapter(IRepositoryComparer comparer) + { + _comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); + } + + public int Compare(object? x, object? y) + { + if (x is IRepositoryView xView && y is IRepositoryView yView) + { + return Compare(xView, yView); + } + + return 0; + } + + private int Compare(IRepositoryView x, IRepositoryView y) + { + return _comparer.Compare(x.Repository, y.Repository); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/IRepository.cs b/src/RepoM.Core.Plugin/IRepository.cs new file mode 100644 index 00000000..32c16257 --- /dev/null +++ b/src/RepoM.Core.Plugin/IRepository.cs @@ -0,0 +1,20 @@ +namespace RepoM.Core.Plugin; + +public interface IRepository +{ + string Name { get; } + + string Path { get; } + + string Location { get; } + + string CurrentBranch { get; } + + string[] Branches { get; } + + string[] LocalBranches { get; } + + string[] Tags { get; } + + string SafePath { get; } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs deleted file mode 100644 index 1d2d05e9..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IPluginRepository.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering; - -public interface IPluginRepository -{ - string Name { get; } - - string CurrentBranch { get; } - - string Path { get; } - - bool IsPinned { get; } - - bool HasUnpushedChanges { get; } -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs index 84fea17c..0178d0cd 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs @@ -2,6 +2,6 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; using System.Collections.Generic; -public interface IRepositoryComparer : IComparer +public interface IRepositoryComparer : IComparer { } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs index b9e346fd..ac5c5143 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparerFactory.cs @@ -2,6 +2,11 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +public interface IRepositoryComparerFactory +{ + IRepositoryComparer Create(IRepositoriesComparerConfiguration configuration); +} + public interface IRepositoryComparerFactory where TConfig : IRepositoriesComparerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs index 67e6eb5a..d60e06da 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs @@ -2,5 +2,5 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; public interface IRepositoryScoreCalculator { - int Score(IPluginRepository repository); + int Score(IRepository repository); } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs index 3cd044e7..10d6343d 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculatorFactory.cs @@ -2,6 +2,11 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +public interface IRepositoryScoreCalculatorFactory +{ + IRepositoryScoreCalculator Create(IRepositoryScorerConfiguration configuration); +} + public interface IRepositoryScoreCalculatorFactory where TConfig : IRepositoryScorerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs index 048f6bed..c60578be 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs @@ -4,7 +4,16 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; public class AzComparer : IRepositoryComparer { - public int Compare(IPluginRepository x, IPluginRepository y) + private readonly int _weight; + private readonly string? _property; + + public AzComparer(int weight, string? property) + { + _weight = weight; + _property = property; + } + + public int Compare(IRepository x, IRepository y) { if (ReferenceEquals(x, y)) { @@ -13,51 +22,35 @@ public int Compare(IPluginRepository x, IPluginRepository y) if (ReferenceEquals(null, y)) { - return 1; + return _weight; } if (ReferenceEquals(null, x)) { - return -1; + return -1 * _weight; } - var nameComparison = string.Compare(x.Name, y.Name, StringComparison.Ordinal); + var comparisonValue = 0; - if (nameComparison < 0) + if ("Name".Equals(_property, StringComparison.InvariantCultureIgnoreCase)) { - return -1; + comparisonValue = string.Compare(x.Name, y.Name, StringComparison.Ordinal); } - - if (nameComparison == 0) + else if ("Location".Equals(_property, StringComparison.InvariantCultureIgnoreCase)) { - return 0; + comparisonValue = string.Compare(x.Location, y.Location, StringComparison.Ordinal); } - return 1; + if (comparisonValue < 0) + { + return -1 * _weight; + } - if (nameComparison != 0) + if (comparisonValue == 0) { - return nameComparison; + return 0; } - // var currentBranchComparison = string.Compare(x.CurrentBranch, y.CurrentBranch, StringComparison.Ordinal); - // if (currentBranchComparison != 0) - // { - // return currentBranchComparison; - // } - // - // var pathComparison = string.Compare(x.Path, y.Path, StringComparison.Ordinal); - // if (pathComparison != 0) - // { - // return pathComparison; - // } - // - // var isPinnedComparison = x.IsPinned.CompareTo(y.IsPinned); - // if (isPinnedComparison != 0) - // { - // return isPinnedComparison; - // } - // - // return x.HasUnpushedChanges.CompareTo(y.HasUnpushedChanges); + return _weight; } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs index 9140cc50..4381514d 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs @@ -4,6 +4,6 @@ public class AzRepositoryComparerFactory : IRepositoryComparerFactory comparers) _comparers = comparers.ToArray(); } - public int Compare(IPluginRepository x, IPluginRepository y) + public int Compare(IRepository x, IRepository y) { if (ReferenceEquals(x, y)) { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs index 4eff69fc..2c6ff892 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs @@ -1,12 +1,19 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; -using System.Collections.Generic; +using System; +using System.Linq; public class CompositionRepositoryComparerFactory : IRepositoryComparerFactory { + private readonly IRepositoryComparerFactory _factory; + + public CompositionRepositoryComparerFactory(IRepositoryComparerFactory factory) + { + _factory = factory ?? throw new ArgumentNullException(nameof(factory)); + } + public IRepositoryComparer Create(CompositionComparerConfigurationV1 configuration) { - // configuration.ScoreProvider - return new CompositionComparer(new List()); + return new CompositionComparer(configuration.Comparers.Select(c => _factory.Create(c))); } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScoreCalculator.cs deleted file mode 100644 index 34a00c7a..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScoreCalculator.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; - -public class IsPinnedScoreCalculator : IRepositoryScoreCalculator -{ - private readonly int _weight; - - public IsPinnedScoreCalculator(int weight) - { - _weight = weight; - } - - public int Score(IPluginRepository repository) - { - return repository.IsPinned ? _weight : 0; - } -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs deleted file mode 100644 index 1a1dbf9c..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/IsPinned/IsPinnedScorerFactory.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; - -public class IsPinnedScorerFactory : IRepositoryScoreCalculatorFactory -{ - public IRepositoryScoreCalculator Create(IsPinnedScorerConfigurationV1 config) - { - return new IsPinnedScoreCalculator(config.Weight); - } -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs index f2ac5125..8840df77 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs @@ -1,16 +1,20 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +using System.Linq; + public class LabelScoreCalculator : IRepositoryScoreCalculator { + private readonly string _label; private readonly int _weight; - public LabelScoreCalculator(int weight) + public LabelScoreCalculator(string label, int weight) { + _label = label; _weight = weight; } - public int Score(IPluginRepository repository) + public int Score(IRepository repository) { - return 0; + return repository.Tags.Contains(_label) ? _weight : 0; } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs index 72b69a2a..0ed157f0 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs @@ -1,7 +1,6 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; public class LabelScorerConfigurationV1 : IRepositoryScorerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs index 343132f0..aecfaab9 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs @@ -1,9 +1,16 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +using System; + public class LabelScorerFactory : IRepositoryScoreCalculatorFactory { public IRepositoryScoreCalculator Create(LabelScorerConfigurationV1 config) { - return new LabelScoreCalculator(config.Weight); + if (string.IsNullOrWhiteSpace(config.Label)) + { + throw new Exception("Label cannot be null"); + } + + return new LabelScoreCalculator(config.Label!, config.Weight); } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs index a7b30957..67f01f83 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs @@ -11,7 +11,7 @@ public ScoreComparer(IRepositoryScoreCalculator calculator) _calculator = calculator ?? throw new ArgumentNullException(nameof(calculator)); } - public int Compare(IPluginRepository x, IPluginRepository y) + public int Compare(IRepository x, IRepository y) { if (ReferenceEquals(x, y)) { @@ -28,6 +28,7 @@ public int Compare(IPluginRepository x, IPluginRepository y) return -1; } - return _calculator.Score(x) - _calculator.Score(y); + var result = _calculator.Score(y) - _calculator.Score(x); + return result; } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs index 942ba828..bc56c03d 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs @@ -1,14 +1,18 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; +using System; public class ScoreRepositoryComparerFactory : IRepositoryComparerFactory { - public IRepositoryComparer Create(ScoreComparerConfigurationV1 configuration) + private readonly IRepositoryScoreCalculatorFactory _factory; + + public ScoreRepositoryComparerFactory(IRepositoryScoreCalculatorFactory factory) { - // configuration.ScoreProvider + _factory = factory ?? throw new ArgumentNullException(nameof(factory)); + } - IRepositoryScoreCalculator calculator = new IsPinnedScoreCalculator(2); - return new ScoreComparer(calculator); + public IRepositoryComparer Create(ScoreComparerConfigurationV1 configuration) + { + return new ScoreComparer(_factory.Create(configuration.ScoreProvider!)); } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs index e39a4d5a..297c48d9 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs @@ -2,7 +2,6 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; public class SumComparerConfigurationV1 : IRepositoriesComparerConfiguration { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs index a516792f..e7f163dc 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs @@ -12,7 +12,7 @@ public SumCompositionComparer(IEnumerable comparers) _comparers = comparers.ToArray(); } - public int Compare(IPluginRepository x, IPluginRepository y) + public int Compare(IRepository x, IRepository y) { if (ReferenceEquals(x, y)) { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs index 91e365c2..1b5d7526 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs @@ -1,12 +1,19 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; -using System.Collections.Generic; +using System; +using System.Linq; public class SumRepositoryComparerFactory : IRepositoryComparerFactory { + private readonly IRepositoryComparerFactory _factory; + + public SumRepositoryComparerFactory(IRepositoryComparerFactory factory) + { + _factory = factory ?? throw new ArgumentNullException(nameof(factory)); + } + public IRepositoryComparer Create(SumComparerConfigurationV1 configuration) { - // configuration.ScoreProvider - return new SumCompositionComparer(new List()); + return new SumCompositionComparer(configuration.Comparers.Select(c => _factory.Create(c))); } } \ No newline at end of file diff --git a/tests/Tests/UI/RepositoryViewTests.cs b/tests/Tests/UI/RepositoryViewTests.cs index 0fef5b70..f95cde46 100644 --- a/tests/Tests/UI/RepositoryViewTests.cs +++ b/tests/Tests/UI/RepositoryViewTests.cs @@ -10,14 +10,14 @@ namespace Tests.UI; public class RepositoryViewTests { private Repository _repo = null!; - private RepositoryView _view = null!; + private RepositoryViewModel _viewModel = null!; private StatusCharacterMap _statusCharacterMap = null!; [SetUp] public void Setup() { _repo = new RepositoryBuilder().BuildFullFeatured(); - _view = new RepositoryView(_repo, A.Dummy()); + _viewModel = new RepositoryViewModel(_repo, A.Dummy()); _statusCharacterMap = new StatusCharacterMap(); } @@ -26,7 +26,7 @@ public class CtorMethod : RepositoryViewTests [Test] public void Throws_If_Null_Is_Passed_As_Argument() { - Action act = () => _ = new RepositoryView(null!, A.Dummy()); + Action act = () => _ = new RepositoryViewModel(null!, A.Dummy()); act.Should().Throw(); } } @@ -36,14 +36,14 @@ public class AheadByProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.AheadBy.Should().Be(_repo.AheadBy.ToString()); + _viewModel.AheadBy.Should().Be(_repo.AheadBy.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.AheadBy = null; - _view.AheadBy.Should().BeEmpty(); + _viewModel.AheadBy.Should().BeEmpty(); } } @@ -52,14 +52,14 @@ public class BehindByProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.BehindBy.Should().Be(_repo.BehindBy.ToString()); + _viewModel.BehindBy.Should().Be(_repo.BehindBy.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.BehindBy = null; - _view.BehindBy.Should().BeEmpty(); + _viewModel.BehindBy.Should().BeEmpty(); } } @@ -68,14 +68,14 @@ public class BranchesProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.Branches.Should().ContainInOrder("master", "feature-one", "feature-two"); + _viewModel.Branches.Should().ContainInOrder("master", "feature-one", "feature-two"); } [Test] public void Returns_An_Empty_Array_For_Null() { _repo.Branches = null!; - _view.Branches.Length.Should().Be(0); + _viewModel.Branches.Length.Should().Be(0); } } @@ -84,14 +84,14 @@ public class CurrentBranchProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value() { - _view.CurrentBranch.Should().Be(_repo.CurrentBranch); + _viewModel.CurrentBranch.Should().Be(_repo.CurrentBranch); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.CurrentBranch = null!; - _view.CurrentBranch.Should().BeEmpty(); + _viewModel.CurrentBranch.Should().BeEmpty(); } } @@ -100,14 +100,14 @@ public class LocalAddedProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.LocalAdded.Should().Be(_repo.LocalAdded.ToString()); + _viewModel.LocalAdded.Should().Be(_repo.LocalAdded.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.LocalAdded = null; - _view.LocalAdded.Should().BeEmpty(); + _viewModel.LocalAdded.Should().BeEmpty(); } } @@ -116,14 +116,14 @@ public class LocalIgnoredProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.LocalIgnored.Should().Be(_repo.LocalIgnored.ToString()); + _viewModel.LocalIgnored.Should().Be(_repo.LocalIgnored.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.LocalIgnored = null; - _view.LocalIgnored.Should().BeEmpty(); + _viewModel.LocalIgnored.Should().BeEmpty(); } } @@ -132,14 +132,14 @@ public class StashCountProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.StashCount.Should().Be(_repo.StashCount.ToString()); + _viewModel.StashCount.Should().Be(_repo.StashCount.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.StashCount = null; - _view.StashCount.Should().BeEmpty(); + _viewModel.StashCount.Should().BeEmpty(); } } @@ -148,14 +148,14 @@ public class LocalMissingProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.LocalMissing.Should().Be(_repo.LocalMissing.ToString()); + _viewModel.LocalMissing.Should().Be(_repo.LocalMissing.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.LocalMissing = null; - _view.LocalMissing.Should().BeEmpty(); + _viewModel.LocalMissing.Should().BeEmpty(); } } @@ -164,14 +164,14 @@ public class LocalModifiedProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.LocalModified.Should().Be(_repo.LocalModified.ToString()); + _viewModel.LocalModified.Should().Be(_repo.LocalModified.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.LocalModified = null; - _view.LocalModified.Should().BeEmpty(); + _viewModel.LocalModified.Should().BeEmpty(); } } @@ -180,14 +180,14 @@ public class LocalRemovedProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.LocalRemoved.Should().Be(_repo.LocalRemoved.ToString()); + _viewModel.LocalRemoved.Should().Be(_repo.LocalRemoved.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.LocalRemoved = null; - _view.LocalRemoved.Should().BeEmpty(); + _viewModel.LocalRemoved.Should().BeEmpty(); } } @@ -196,14 +196,14 @@ public class LocalStagedProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.LocalStaged.Should().Be(_repo.LocalStaged.ToString()); + _viewModel.LocalStaged.Should().Be(_repo.LocalStaged.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.LocalStaged = null; - _view.LocalStaged.Should().BeEmpty(); + _viewModel.LocalStaged.Should().BeEmpty(); } } @@ -212,14 +212,14 @@ public class LocalUntrackedProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value_As_String() { - _view.LocalUntracked.Should().Be(_repo.LocalUntracked.ToString()); + _viewModel.LocalUntracked.Should().Be(_repo.LocalUntracked.ToString()); } [Test] public void Returns_An_Empty_String_For_Null() { _repo.LocalUntracked = null; - _view.LocalUntracked.Should().BeEmpty(); + _viewModel.LocalUntracked.Should().BeEmpty(); } } @@ -228,7 +228,7 @@ public class NameProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value() { - _view.Name.Should().Be(_repo.Name); + _viewModel.Name.Should().Be(_repo.Name); } } @@ -237,7 +237,7 @@ public class PathProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value() { - _view.Path.Should().Be(_repo.Path); + _viewModel.Path.Should().Be(_repo.Path); } } @@ -247,7 +247,7 @@ public class StatusProperty : RepositoryViewTests public void Returns_The_Compressed_String_From_The_StatusCompressor_Helper_Class() { var expected = new StatusCompressor(_statusCharacterMap).Compress(_repo); - _view.Status.Should().Be(expected); + _viewModel.Status.Should().Be(expected); } } @@ -256,21 +256,21 @@ public class MatchesFilterMethod : RepositoryViewTests [Test] public void Returns_True_If_Filter_Is_Empty() { - _view.MatchesFilter("").Should().Be(true); + _viewModel.MatchesFilter("").Should().Be(true); } [Test] public void Can_Filter_By_Name_Implicit() { _repo.Name = "Hello World"; - _view.MatchesFilter("lo wo").Should().Be(true); + _viewModel.MatchesFilter("lo wo").Should().Be(true); } [Test] public void Can_Filter_By_Name_Explicit() { _repo.Name = "Hello World"; - _view.MatchesFilter("n lo wo").Should().Be(true); + _viewModel.MatchesFilter("n lo wo").Should().Be(true); } [Test] @@ -278,7 +278,7 @@ public void Can_Filter_By_Branch() { _repo.Name = "No Match Here"; _repo.CurrentBranch = "feature/Test"; - _view.MatchesFilter("b feat").Should().Be(true); + _viewModel.MatchesFilter("b feat").Should().Be(true); } [Test] @@ -286,14 +286,14 @@ public void Can_Filter_By_Path() { _repo.Name = "No Match Here"; _repo.Path = @"C:\Test\Path"; - _view.MatchesFilter(@"p C:\").Should().Be(true); + _viewModel.MatchesFilter(@"p C:\").Should().Be(true); } [Test] public void Returns_True_If_Filter_Is_Empty_Except_Prefix() { // "n ", "b ", "p " can be used to filter for name, branch and path - _view.MatchesFilter("b ").Should().Be(true); + _viewModel.MatchesFilter("b ").Should().Be(true); } [Test] @@ -301,7 +301,7 @@ public void Returns_False_If_Prefix_Misses_Space() { // should be interpreted as "b" search term without prefix _repo.Name = "xyz"; - _view.MatchesFilter("b").Should().Be(false); + _viewModel.MatchesFilter("b").Should().Be(false); } [Test] @@ -309,7 +309,7 @@ public void Returns_False_If_Prefix_Comes_With_Two_Spaces() { // trimming "b " leads to " master" which is not trimmed by design _repo.CurrentBranch = "master"; - _view.MatchesFilter("b master").Should().Be(false); + _viewModel.MatchesFilter("b master").Should().Be(false); } [Test] @@ -317,7 +317,7 @@ public void Returns_True_For_ToDo_Filter_With_UnpushedChanges() { _repo.StashCount = 1; _repo.HasUnpushedChanges.Should().Be(true); - _view.MatchesFilter("todo").Should().Be(true); + _viewModel.MatchesFilter("todo").Should().Be(true); } [Test] @@ -325,7 +325,7 @@ public void Returns_False_For_ToDo_Filter_Without_UnpushedChanges() { _repo = new Repository(); _repo.HasUnpushedChanges.Should().Be(false); - new RepositoryView(_repo, A.Dummy()).MatchesFilter("todo").Should().Be(false); + new RepositoryViewModel(_repo, A.Dummy()).MatchesFilter("todo").Should().Be(false); } } @@ -334,14 +334,14 @@ public class WasFoundProperty : RepositoryViewTests [Test] public void Returns_The_Repository_Value() { - _view.WasFound.Should().Be(_repo.WasFound); + _viewModel.WasFound.Should().Be(_repo.WasFound); } [Test] public void Returns_False_If_Path_Is_Empty() { _repo.Path = ""; - _view.WasFound.Should().BeFalse(); + _viewModel.WasFound.Should().BeFalse(); } } @@ -350,7 +350,7 @@ public class GetHashCodeMethod : RepositoryViewTests [Test] public void Returns_The_Repository_Value() { - _view.GetHashCode().Should().Be(_repo.GetHashCode()); + _viewModel.GetHashCode().Should().Be(_repo.GetHashCode()); } } } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs index 688ee735..52a9fb23 100644 --- a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs +++ b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs @@ -1,36 +1,127 @@ namespace Yaml.Poc.Tests.DI; +using System; +using System.Threading.Tasks; +using RepoM.Api.Git; +using RepoM.Api.Ordering.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using SimpleInjector; using Container = SimpleInjector.Container; + +internal class RepositoryComparerCompositionFactory : IRepositoryComparerFactory +{ + private readonly Container _container; + + public RepositoryComparerCompositionFactory(Container container) + { + _container = container; + } + + public IRepositoryComparer Create(IRepositoriesComparerConfiguration configuration) + { + Type type = typeof(IRepositoryComparerFactory<>).MakeGenericType(configuration.GetType()); + dynamic factory = _container.GetInstance(type); + return factory.Create((dynamic)configuration); + } +} + +internal class RepositoryScoreCalculatorFactory : IRepositoryScoreCalculatorFactory +{ + private readonly Container _container; + + public RepositoryScoreCalculatorFactory(Container container) + { + _container = container; + } + + public IRepositoryScoreCalculator Create(IRepositoryScorerConfiguration configuration) + { + Type type = typeof(IRepositoryScoreCalculatorFactory<>).MakeGenericType(configuration.GetType()); + dynamic factory = _container.GetInstance(type); + return factory.Create((dynamic)configuration); + } + +} + +internal class DummyIRepositoryMonitor : IRepositoryMonitor +{ + public event EventHandler? OnChangeDetected; + public event EventHandler? OnDeletionDetected; + public event EventHandler? OnScanStateChanged; + public void Stop() + { + throw new NotImplementedException(); + } + + public void Observe() + { + throw new NotImplementedException(); + } + + public void Reset() + { + throw new NotImplementedException(); + } + + public Task ScanForLocalRepositoriesAsync() + { + throw new NotImplementedException(); + } + + public void IgnoreByPath(string path) + { + throw new NotImplementedException(); + } + + public void SetPinned(bool newValue, Repository repository) + { + throw new NotImplementedException(); + } + + public bool IsPinned(Repository repository) + { + throw new NotImplementedException(); + } +} + internal static class Bootstrapper { public static void RegisterOrderingConfiguration(Container container) { + container.RegisterSingleton(); + container.RegisterSingleton(); + container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); + container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register(); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); + container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, LabelScorerFactory>(Lifestyle.Singleton); + container.Register, LabelScorerFactory>(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, SumRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, SumRepositoryComparerFactory>(Lifestyle.Singleton); } } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj index c17a6b5f..7ead70a6 100644 --- a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj +++ b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj @@ -37,6 +37,7 @@ + diff --git a/tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt b/tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt new file mode 100644 index 00000000..654929da --- /dev/null +++ b/tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt @@ -0,0 +1,16 @@ +{ + Comparers: [ + { + $type: AlphabetComparerConfigurationV1, + Property: Name, + Weight: 1 + }, + { + $type: ScoreComparerConfigurationV1, + ScoreProvider: { + $type: IsPinnedScorerConfigurationV1, + Weight: 5 + } + } + ] +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index 1831b31d..693b97c3 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -1,12 +1,13 @@ namespace Yaml.Poc.Tests; +using System; using System.Collections.Generic; using System.Threading.Tasks; -using FakeItEasy; +using RepoM.Api.Ordering.IsPinned; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using SimpleInjector; @@ -19,7 +20,7 @@ namespace Yaml.Poc.Tests; [UsesVerify] public class YamlTests { - private readonly string yml = @" + private const string YML = @" !sum-comparer@1 comparers: - !az-comparer@1 @@ -31,6 +32,18 @@ public class YamlTests weight: 5 "; + private const string YML1 = @" + !sum-comparer@1 + comparers: + - !az-comparer@1 + property: Name + weight: 1 + - !score-comparer@1 + score-provider: + !is-pinned-scorer@1 + weight: 5 +"; + //https://github.com/aaubry/YamlDotNet/wiki/Serialization.Deserializer [Fact] public async Task Abc() @@ -43,7 +56,7 @@ public async Task Abc() .WithTagMapping("!is-pinned-scorer@1", typeof(IsPinnedScorerConfigurationV1)) .Build(); - var result = deserializer.Deserialize(yml); + var result = deserializer.Deserialize(YML); await Verifier.Verify(result); } @@ -66,11 +79,32 @@ public async Task DI() } IDeserializer deserializer = builder.Build(); - - - IRepositoriesComparerConfiguration result = deserializer.Deserialize(yml); + + IRepositoriesComparerConfiguration result = deserializer.Deserialize(YML1); // var instance2s = container.GetAllInstances>(); // IRepositoryComparerFactory - await Verifier.Verify(result).UseMethodName(nameof(Abc)); + await Verifier.Verify(result); + + IRepositoryComparerFactory factory = container.GetInstance(); + var comparer = factory.Create(result); + + var repo = new R { Name = "Rian", IsPinned = true,}; + var repo2 = new R { Name = "Coen", IsPinned = false, }; + + int r = comparer.Compare(repo, repo2); } +} + +public class R : IRepository +{ + public string Name { get; set; } + public string Location { get; } + public string CurrentBranch { get; set; } + public string[] Branches { get; } + public string[] LocalBranches { get; } + public string SafePath { get; } + public string Path { get; set; } + public bool IsPinned { get; set; } + public bool HasUnpushedChanges { get; set; } + public string[] Tags { get; set; } = Array.Empty(); } \ No newline at end of file From 10ac4c1c689b1a6699e4383bc835f41ebd563ebc Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Thu, 24 Nov 2022 22:19:43 +0100 Subject: [PATCH 15/60] fix --- tests/Yaml.Poc.Tests/DI/Bootstrapper.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs index 52a9fb23..0a76729f 100644 --- a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs +++ b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs @@ -101,13 +101,12 @@ public static void RegisterOrderingConfiguration(Container container) container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); - - + container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); - container.Register(); + container.Register(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); From 3c3ab68dbbbbb09601d138247095e8dd0c4a1609 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 25 Nov 2022 09:26:26 +0100 Subject: [PATCH 16/60] FIle service --- .../Common/FileAppSettingsService.cs | 60 +++++++++++++ src/RepoM.Api/Common/IAppSettingsService.cs | 6 ++ src/RepoM.App/App.xaml.cs | 86 ++++++++++++++++++- src/RepoM.App/MainWindow.xaml.cs | 21 ++--- .../Label/LabelScoreCalculator.cs | 20 ----- .../LabelScorerConfigurationV1Registration.cs | 11 --- .../Label/LabelScorerFactory.cs | 16 ---- .../Label/TagScoreCalculator.cs | 20 +++++ ...ationV1.cs => TagScorerConfigurationV1.cs} | 4 +- .../TagScorerConfigurationV1Registration.cs | 11 +++ .../Implementations/Label/TagScorerFactory.cs | 16 ++++ tests/Yaml.Poc.Tests/DI/Bootstrapper.cs | 6 +- tests/Yaml.Poc.Tests/DI/Class1.cs | 1 - 13 files changed, 208 insertions(+), 70 deletions(-) delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs delete mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScoreCalculator.cs rename src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/{LabelScorerConfigurationV1.cs => TagScorerConfigurationV1.cs} (60%) create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1Registration.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerFactory.cs diff --git a/src/RepoM.Api/Common/FileAppSettingsService.cs b/src/RepoM.Api/Common/FileAppSettingsService.cs index 0c92a184..89225893 100644 --- a/src/RepoM.Api/Common/FileAppSettingsService.cs +++ b/src/RepoM.Api/Common/FileAppSettingsService.cs @@ -8,6 +8,66 @@ namespace RepoM.Api.Common; using Newtonsoft.Json; using RepoM.Api.Git.AutoFetch; using RepoM.Api.IO; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +public class FilesICompareSettingsService : ICompareSettingsService +{ + private readonly IFileSystem _fileSystem; + private readonly IEnumerable _registrations; + private readonly IAppDataPathProvider _appDataPathProvider; + private IRepositoriesComparerConfiguration? _settings; + + public FilesICompareSettingsService(IAppDataPathProvider appDataPathProvider, IFileSystem fileSystem, IEnumerable registrations) + { + _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); + _registrations = registrations.ToList(); + _appDataPathProvider = appDataPathProvider ?? throw new ArgumentNullException(nameof(appDataPathProvider)); + } + + public IRepositoriesComparerConfiguration Configuration => _settings ??= Load(); + + private string GetFileName() + { + return Path.Combine(_appDataPathProvider.GetAppDataPath(), "RepoM.Ordering.yaml"); + } + + private IRepositoriesComparerConfiguration Load() + { + var file = GetFileName(); + + if (!_fileSystem.File.Exists(file)) + { + throw new Exception("File doesnot exist"); + } + + try + { + var yml = _fileSystem.File.ReadAllText(file); + + + DeserializerBuilder builder = new DeserializerBuilder() + .WithNamingConvention(HyphenatedNamingConvention.Instance); + + foreach (IConfigurationRegistration instance in _registrations) + { + var tag = instance.Tag.TrimStart('!'); + builder.WithTagMapping("!" + tag, instance.ConfigurationType); + } + + IDeserializer deserializer = builder.Build(); + + return deserializer.Deserialize(yml); + } + catch + { + throw; + /* Our app settings are not critical. For our purposes, we want to ignore IO exceptions */ + } + + } +} public class FileAppSettingsService : IAppSettingsService { diff --git a/src/RepoM.Api/Common/IAppSettingsService.cs b/src/RepoM.Api/Common/IAppSettingsService.cs index 043880e5..69791251 100644 --- a/src/RepoM.Api/Common/IAppSettingsService.cs +++ b/src/RepoM.Api/Common/IAppSettingsService.cs @@ -3,6 +3,12 @@ namespace RepoM.Api.Common; using System; using System.Collections.Generic; using RepoM.Api.Git.AutoFetch; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public interface ICompareSettingsService +{ + IRepositoriesComparerConfiguration Configuration { get; } +} public interface IAppSettingsService { diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index 1dc1dcd9..ca7e576a 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -35,6 +35,51 @@ namespace RepoM.App; using ILogger = Microsoft.Extensions.Logging.ILogger; using RepoM.App.Services; using RepoM.Api.IO.VariableProviders; +using RepoM.Api.Ordering.IsPinned; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; +using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; +using RepoM.Core.Plugin.RepositoryOrdering; +using System.ComponentModel; +using Container = SimpleInjector.Container; + +internal class RepositoryComparerCompositionFactory : IRepositoryComparerFactory +{ + private readonly Container _container; + + public RepositoryComparerCompositionFactory(Container container) + { + _container = container; + } + + public IRepositoryComparer Create(IRepositoriesComparerConfiguration configuration) + { + Type type = typeof(IRepositoryComparerFactory<>).MakeGenericType(configuration.GetType()); + dynamic factory = _container.GetInstance(type); + return factory.Create((dynamic)configuration); + } +} + +internal class RepositoryScoreCalculatorFactory : IRepositoryScoreCalculatorFactory +{ + private readonly Container _container; + + public RepositoryScoreCalculatorFactory(Container container) + { + _container = container; + } + + public IRepositoryScoreCalculator Create(IRepositoryScorerConfiguration configuration) + { + Type type = typeof(IRepositoryScoreCalculatorFactory<>).MakeGenericType(configuration.GetType()); + dynamic factory = _container.GetInstance(type); + return factory.Create((dynamic)configuration); + } + +} /// /// Interaction logic for App.xaml @@ -69,7 +114,6 @@ protected override void OnStartup(StartupEventArgs e) new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag))); Application.Current.Resources.MergedDictionaries[0] = ResourceDictionaryTranslationService.ResourceDictionary; - _notifyIcon = FindResource("NotifyIcon") as TaskbarIcon; var fileSystem = new FileSystem(); @@ -82,6 +126,7 @@ protected override void OnStartup(StartupEventArgs e) RegisterServices(_container, fileSystem); UseRepositoryMonitor(_container); + _container.Verify(VerificationOption.VerifyAndDiagnose); _updateTimer = new Timer(async _ => await CheckForUpdatesAsync(), null, 5000, Timeout.Infinite); @@ -208,6 +253,7 @@ private static void RegisterServices(Container container, IFileSystem fileSystem container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); + container.Register (Lifestyle.Singleton); container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); @@ -266,6 +312,44 @@ private static void RegisterServices(Container container, IFileSystem fileSystem IEnumerable pluginDlls = PluginFinder.FindPluginAssemblies(Path.Combine(AppDomain.CurrentDomain.BaseDirectory), fileSystem); IEnumerable assemblies = pluginDlls.Select(plugin => Assembly.Load(AssemblyName.GetAssemblyName(plugin.FullName))); container.RegisterPackages(assemblies); + + + + + + _container.RegisterSingleton(); + _container.RegisterSingleton(); + + _container.Collection.Register(typeof(IConfigurationRegistration), new[] { typeof(IConfigurationRegistration).Assembly, typeof(IsPinnedScorerConfigurationV1Registration).Assembly, }, Lifestyle.Singleton); + + // _container.Collection.Append(Lifestyle.Singleton); + _container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); + _container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); + + // _container.Collection.Append(Lifestyle.Singleton); + _container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + _container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + + // _container.Collection.Append(Lifestyle.Singleton); + _container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); + _container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); + + // _container.Collection.Append(Lifestyle.Singleton); + _container.Collection.Append, TagScorerFactory>(Lifestyle.Singleton); + _container.Register, TagScorerFactory>(Lifestyle.Singleton); + + // _container.Collection.Append(Lifestyle.Singleton); + _container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); + _container.Register, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); + + // _container.Collection.Append(Lifestyle.Singleton); + _container.Collection.Append, SumRepositoryComparerFactory>(Lifestyle.Singleton); + _container.Register, SumRepositoryComparerFactory>(Lifestyle.Singleton); + + + + + } private static void StartModules(List modules) diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index c2d3e0d8..950e20c4 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -17,15 +17,9 @@ namespace RepoM.App; using RepoM.Api.Common; using RepoM.Api.Git; using RepoM.Api.IO; -using RepoM.Api.Ordering.IsPinned; using RepoM.App.Controls; using RepoM.App.Services; -using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryOrdering; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; using SourceChord.FluentWPF; /// @@ -54,7 +48,9 @@ public MainWindow( ITranslationService translationService, IAppDataPathProvider appDataPathProvider, IRepositorySearch repositorySearch, - IFileSystem fileSystem) + IFileSystem fileSystem, + ICompareSettingsService compareSettingsService, + IRepositoryComparerFactory repositoryComparerFactory) { _translationService = translationService; InitializeComponent(); @@ -82,15 +78,8 @@ public MainWindow( var view = (ListCollectionView)CollectionViewSource.GetDefaultView(aggregator.Repositories); ((ICollectionView)view).CollectionChanged += View_CollectionChanged; view.Filter = FilterRepositories; - view.CustomSort = new RepositoryComparerAdapter( - new CompositionComparer( - new IRepositoryComparer[] - { - new ScoreComparer(new IsPinnedScoreCalculator(repositoryMonitor, 1)), - // new ScoreComparer(new LabelScoreCalculator("Prive", 1)), - new AzComparer(1, nameof(IRepository.Name)), - } - )); + view.CustomSort = new RepositoryComparerAdapter(repositoryComparerFactory.Create(compareSettingsService.Configuration)); + AssemblyName? appName = Assembly.GetEntryAssembly()?.GetName(); txtHelpCaption.Text = appName?.Name + " " + appName?.Version?.ToString(2); diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs deleted file mode 100644 index 8840df77..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScoreCalculator.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; - -using System.Linq; - -public class LabelScoreCalculator : IRepositoryScoreCalculator -{ - private readonly string _label; - private readonly int _weight; - - public LabelScoreCalculator(string label, int weight) - { - _label = label; - _weight = weight; - } - - public int Score(IRepository repository) - { - return repository.Tags.Contains(_label) ? _weight : 0; - } -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs deleted file mode 100644 index d5d5f66c..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1Registration.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; - -using System; -using RepoM.Core.Plugin.RepositoryOrdering.Configuration; - -public class LabelScorerConfigurationV1Registration : IConfigurationRegistration -{ - public Type ConfigurationType { get; } = typeof(LabelScorerConfigurationV1); - - public string Tag { get; } = "label-scorer@1"; -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs deleted file mode 100644 index aecfaab9..00000000 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; - -using System; - -public class LabelScorerFactory : IRepositoryScoreCalculatorFactory -{ - public IRepositoryScoreCalculator Create(LabelScorerConfigurationV1 config) - { - if (string.IsNullOrWhiteSpace(config.Label)) - { - throw new Exception("Label cannot be null"); - } - - return new LabelScoreCalculator(config.Label!, config.Weight); - } -} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScoreCalculator.cs new file mode 100644 index 00000000..b71eaef7 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScoreCalculator.cs @@ -0,0 +1,20 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; + +using System.Linq; + +public class TagScoreCalculator : IRepositoryScoreCalculator +{ + private readonly string _tag; + private readonly int _weight; + + public TagScoreCalculator(string tag, int weight) + { + _tag = tag; + _weight = weight; + } + + public int Score(IRepository repository) + { + return repository.Tags.Contains(_tag) ? _weight : 0; + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1.cs similarity index 60% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs rename to src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1.cs index 0ed157f0..6e7f98d3 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/LabelScorerConfigurationV1.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1.cs @@ -2,9 +2,9 @@ namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class LabelScorerConfigurationV1 : IRepositoryScorerConfiguration +public class TagScorerConfigurationV1 : IRepositoryScorerConfiguration { public int Weight { get; set; } - public string? Label { get; set; } + public string? Tag { get; set; } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1Registration.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1Registration.cs new file mode 100644 index 00000000..243d3ab0 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1Registration.cs @@ -0,0 +1,11 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class TagScorerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(TagScorerConfigurationV1); + + public string Tag { get; } = "tag-scorer@1"; +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerFactory.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerFactory.cs new file mode 100644 index 00000000..e7ac1f81 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerFactory.cs @@ -0,0 +1,16 @@ +namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; + +using System; + +public class TagScorerFactory : IRepositoryScoreCalculatorFactory +{ + public IRepositoryScoreCalculator Create(TagScorerConfigurationV1 config) + { + if (string.IsNullOrWhiteSpace(config.Tag)) + { + throw new Exception("Tag cannot be null"); + } + + return new TagScoreCalculator(config.Tag!, config.Weight); + } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs index 0a76729f..ad1643b1 100644 --- a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs +++ b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs @@ -111,9 +111,9 @@ public static void RegisterOrderingConfiguration(Container container) container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, LabelScorerFactory>(Lifestyle.Singleton); - container.Register, LabelScorerFactory>(Lifestyle.Singleton); + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, TagScorerFactory>(Lifestyle.Singleton); + container.Register, TagScorerFactory>(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); diff --git a/tests/Yaml.Poc.Tests/DI/Class1.cs b/tests/Yaml.Poc.Tests/DI/Class1.cs index 7dc13119..83d2aef5 100644 --- a/tests/Yaml.Poc.Tests/DI/Class1.cs +++ b/tests/Yaml.Poc.Tests/DI/Class1.cs @@ -1,6 +1,5 @@ namespace Yaml.Poc.Tests.DI; -using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using System.Threading; using System; From 6453dbc5b1cac75ac3dc0b14700f1e774a5c5a6b Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 25 Nov 2022 11:55:34 +0100 Subject: [PATCH 17/60] fix sonar --- src/RepoM.App/MainWindow.xaml.cs | 2 +- .../ActionSonarCloudV1Mapper.cs | 38 ++++++++++++------- .../SonarCloudFavoriteService.cs | 2 + 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index 950e20c4..6ef0f88f 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -419,7 +419,7 @@ private void ShowUpdateIfAvailable() } }; - var item = new AcrylicMenuItem() + var item = new AcrylicMenuItem { Header = repositoryAction.Name, IsEnabled = repositoryAction.CanExecute, diff --git a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs index 26a1b350..d31130b4 100644 --- a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs +++ b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs @@ -61,20 +61,30 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository var name = NameHelper.EvaluateName(action.Name, repository, _translationService, _expressionEvaluator); var key = _expressionEvaluator.EvaluateStringExpression(action.Project!, repository); - yield return new Api.Git.RepositoryAction(name) - { - Action = (_, _) => - { - try - { - _ = _service.SetFavorite(key); - } - catch (Exception) + if (_service.IsInitialized) + { + yield return new Api.Git.RepositoryAction(name) + { + Action = (_, _) => { - // ignore - } - }, - ExecutionCausesSynchronizing = false, - }; + try + { + _ = _service.SetFavorite(key); + } + catch (Exception) + { + // ignore + } + }, + ExecutionCausesSynchronizing = false, + }; + } + else + { + yield return new Api.Git.RepositoryAction(name) + { + CanExecute = false, + }; + } } } \ No newline at end of file diff --git a/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs b/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs index 5afb3025..05b723c9 100644 --- a/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs +++ b/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs @@ -45,6 +45,8 @@ public Task InitializeAsync() return Task.CompletedTask; } + public bool IsInitialized => (_client != null); + public async Task SetFavorite(string repoKey) { SonarQubeClient? c = _client; From 86a1912c827f65382b37e6342b568057454c7100 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 25 Nov 2022 15:02:30 +0100 Subject: [PATCH 18/60] sonar --- src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs b/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs index 05b723c9..4cbabf32 100644 --- a/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs +++ b/src/RepoM.Plugin.SonarCloud/SonarCloudFavoriteService.cs @@ -45,7 +45,7 @@ public Task InitializeAsync() return Task.CompletedTask; } - public bool IsInitialized => (_client != null); + public bool IsInitialized => _client != null; public async Task SetFavorite(string repoKey) { From a942a642d15ab181cb52cdfc7cad915b0bcdbc46 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sat, 26 Nov 2022 16:57:29 +0100 Subject: [PATCH 19/60] abstraction around actions --- src/RepoM.Api/Git/RepositoryAction.cs | 5 ++- .../ActionAssociateFileV1Mapper.cs | 8 +++-- .../ActionBrowseRepositoryV1Mapper.cs | 6 ++-- .../ActionMappers/ActionBrowserV1Mapper.cs | 4 ++- .../ActionMappers/ActionCommandV1Mapper.cs | 8 +++-- .../ActionMappers/ActionExecutableV1Mapper.cs | 6 ++-- .../ActionGitCheckoutV1Mapper.cs | 6 ++-- .../ActionPinRepositoryV1Mapper.cs | 4 ++- .../RepositorySpecificConfiguration.cs | 4 ++- .../IO/MultipleRepositoryActionHelper.cs | 6 ++-- .../LoggerActionExecutorDecorator.cs | 18 +++++++++++ .../Executors/Browse/BrowseActionExecutor.cs | 11 +++++++ .../Delegate/DelegateActionExecutor.cs | 19 ++++++++++++ .../Executors/Null/NullActionExecutor.cs | 12 +++++++ src/RepoM.App/MainWindow.xaml.cs | 31 +++++++++++++------ .../RepositoryActions/Actions/BrowseAction.cs | 7 +++++ .../Actions/DelegateAction.cs | 14 +++++++++ .../RepositoryActions/Actions/NullAction.cs | 12 +++++++ .../RepositoryActions/IAction.cs | 5 +++ .../RepositoryActions/IActionExecutor.cs | 6 ++++ .../ActionAzureDevOpsPullRequestsV1Mapper.cs | 6 ++-- .../ActionSonarCloudV1Mapper.cs | 6 ++-- 22 files changed, 173 insertions(+), 31 deletions(-) create mode 100644 src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs create mode 100644 src/RepoM.Api/RepositoryActions/Executors/Browse/BrowseActionExecutor.cs create mode 100644 src/RepoM.Api/RepositoryActions/Executors/Delegate/DelegateActionExecutor.cs create mode 100644 src/RepoM.Api/RepositoryActions/Executors/Null/NullActionExecutor.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryActions/Actions/BrowseAction.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryActions/Actions/NullAction.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryActions/IAction.cs create mode 100644 src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs diff --git a/src/RepoM.Api/Git/RepositoryAction.cs b/src/RepoM.Api/Git/RepositoryAction.cs index edf5e451..0fec110e 100644 --- a/src/RepoM.Api/Git/RepositoryAction.cs +++ b/src/RepoM.Api/Git/RepositoryAction.cs @@ -2,11 +2,14 @@ namespace RepoM.Api.Git; using System; using System.Collections.Generic; +using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.RepositoryActions.Actions; public class RepositorySeparatorAction : RepositoryActionBase { } + public class RepositoryAction : RepositoryActionBase { public RepositoryAction(string name) @@ -19,7 +22,7 @@ public RepositoryAction(string name) public abstract class RepositoryActionBase { - public Action? Action { get; set; } + public IAction Action { get; set; } = NullAction.Instance; public bool ExecutionCausesSynchronizing { get; set; } diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs index f0157e29..99db40d1 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs @@ -8,6 +8,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; public class ActionAssociateFileV1Mapper : IActionToRepositoryActionMapper @@ -70,11 +72,11 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository } } - private RepoM.Api.Git.RepositoryAction CreateProcessRunnerAction(string name, string process, string arguments = "") + private Git.RepositoryAction CreateProcessRunnerAction(string name, string process, string arguments = "") { - return new RepoM.Api.Git.RepositoryAction(name) + return new Git.RepositoryAction(name) { - Action = (_, _) => ProcessHelper.StartProcess(process, arguments), + Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(process, arguments)), }; } diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs index 52152269..6ac772bc 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs @@ -7,6 +7,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; public class ActionBrowseRepositoryV1Mapper : IActionToRepositoryActionMapper { @@ -82,11 +84,11 @@ private IEnumerable Map(RepositoryActionBrowseRepositoryV1? ac }; } - private RepositoryAction CreateProcessRunnerAction(string name, string process, string arguments = "") + private static RepositoryAction CreateProcessRunnerAction(string name, string process, string arguments = "") { return new RepositoryAction(name) { - Action = (_, _) => ProcessHelper.StartProcess(process, arguments), + Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(process, arguments)), }; } } \ No newline at end of file diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs index 88be83b1..bda03a8a 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs @@ -7,6 +7,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.Git.RepositoryAction; public class ActionBrowserV1Mapper : IActionToRepositoryActionMapper @@ -56,7 +58,7 @@ private IEnumerable Map(RepositoryActionBrowserV1? action, Rep var url = _expressionEvaluator.EvaluateStringExpression(action.Url, repository); yield return new RepositoryAction(name) { - Action = (_, _) => ProcessHelper.StartProcess(url, string.Empty), + Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(url, string.Empty)), }; } } \ No newline at end of file diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs index b6f005d4..3d155f58 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs @@ -7,6 +7,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; public class ActionCommandV1Mapper : IActionToRepositoryActionMapper @@ -35,7 +37,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository return Map(action as RepositoryActionCommandV1, repository.First()); } - private IEnumerable Map(RepositoryActionCommandV1? action, Repository repository) + private IEnumerable Map(RepositoryActionCommandV1? action, Repository repository) { if (action == null) { @@ -51,9 +53,9 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository var command = _expressionEvaluator.EvaluateStringExpression(action.Command ?? string.Empty, repository); var arguments = _expressionEvaluator.EvaluateStringExpression(action.Arguments ?? string.Empty, repository); - yield return new RepoM.Api.Git.RepositoryAction(name) + yield return new Git.RepositoryAction(name) { - Action = (_, _) => ProcessHelper.StartProcess(command, arguments), + Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(command, arguments)), }; } } \ No newline at end of file diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs index 914ab07c..daa8139e 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs @@ -8,6 +8,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; public class ActionExecutableV1Mapper : IActionToRepositoryActionMapper @@ -76,9 +78,9 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository arguments = _expressionEvaluator.EvaluateStringExpression(action.Arguments, repository); } - yield return new RepoM.Api.Git.RepositoryAction(name) + yield return new Git.RepositoryAction(name) { - Action = (_, _) => ProcessHelper.StartProcess(normalized, arguments), + Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(normalized, arguments)) }; found = true; } diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs index b1c9f3ad..9fd07d06 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs @@ -7,6 +7,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = Data.RepositoryAction; public class ActionGitCheckoutV1Mapper : IActionToRepositoryActionMapper @@ -67,7 +69,7 @@ private IEnumerable Map(RepositoryActionGitCheckoutV1? act .Take(50) .Select(branch => new Git.RepositoryAction(branch) { - Action = (_, _) => _repositoryWriter.Checkout(repository, branch), + Action = new DelegateAction((_, _) => _repositoryWriter.Checkout(repository, branch)), CanExecute = !repository.CurrentBranch.Equals(branch, StringComparison.OrdinalIgnoreCase), }) .Union(new RepositoryActionBase[] @@ -81,7 +83,7 @@ private IEnumerable Map(RepositoryActionGitCheckoutV1? act .ReadAllBranches() .Select(branch => new Git.RepositoryAction(branch) { - Action = (_, _) => _repositoryWriter.Checkout(repository, branch), + Action = new DelegateAction((_, _) => _repositoryWriter.Checkout(repository, branch)), CanExecute = !repository.CurrentBranch.Equals(branch, StringComparison.OrdinalIgnoreCase), }) .ToArray(); diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs index 779a4360..05af288e 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs @@ -7,6 +7,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; public class ActionPinRepositoryV1Mapper : IActionToRepositoryActionMapper @@ -87,7 +89,7 @@ Git.RepositoryAction CreateAction(string name, Repository repository, bool newPi { return new Git.RepositoryAction(name) { - Action = (_, _) => _repositoryMonitor.SetPinned(newPinnedValue, repository), + Action = new DelegateAction((_, _) => _repositoryMonitor.SetPinned(newPinnedValue, repository)), }; } diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs index 83151597..684a71a5 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs @@ -16,6 +16,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Deserialization; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Exceptions; using RepoM.Api.IO.Variables; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using Repository = RepoM.Api.Git.Repository; using RepositoryAction = RepoM.Api.Git.RepositoryAction; @@ -525,7 +527,7 @@ private IEnumerable CreateFailing(Exception ex, string? filena { yield return new RepositoryAction(_translationService.Translate("Fix")) { - Action = (_, _) => ProcessHelper.StartProcess(_fileSystem.Path.GetDirectoryName(filename), string.Empty), + Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(_fileSystem.Path.GetDirectoryName(filename), string.Empty)), }; } } diff --git a/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs b/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs index 26b6f237..51b06c7a 100644 --- a/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs +++ b/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs @@ -4,6 +4,8 @@ namespace RepoM.Api.IO; using System.Collections.Generic; using System.Linq; using RepoM.Api.Git; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; public static class MultipleRepositoryActionHelper { @@ -15,7 +17,7 @@ public static RepositoryAction CreateActionForMultipleRepositories( { return new RepositoryAction(name) { - Action = (_, _) => + Action = new DelegateAction((_, _) => { // copy over to an array to not get an exception // once the enumerator changes (which can happen when a change @@ -26,7 +28,7 @@ public static RepositoryAction CreateActionForMultipleRepositories( { SafelyExecute(action, repository); // git/io-exceptions will break the loop, put in try/catch } - }, + }), ExecutionCausesSynchronizing = executionCausesSynchronizing, }; } diff --git a/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs b/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs new file mode 100644 index 00000000..6ee7a424 --- /dev/null +++ b/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs @@ -0,0 +1,18 @@ +namespace RepoM.Api.RepositoryActions.Decorators; + +using RepoM.Core.Plugin.RepositoryActions; + +public class LoggerActionExecutorDecorator : IActionExecutor where T : IAction +{ + private readonly IActionExecutor _decoratee; + + public LoggerActionExecutorDecorator(IActionExecutor decoratee) + { + _decoratee = decoratee; + } + + public void Execute(T action) + { + _decoratee.Execute(action); + } +} \ No newline at end of file diff --git a/src/RepoM.Api/RepositoryActions/Executors/Browse/BrowseActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/Browse/BrowseActionExecutor.cs new file mode 100644 index 00000000..c2e6dc61 --- /dev/null +++ b/src/RepoM.Api/RepositoryActions/Executors/Browse/BrowseActionExecutor.cs @@ -0,0 +1,11 @@ +namespace RepoM.Api.RepositoryActions.Executors.Browse; + +using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.RepositoryActions.Actions; + +public class BrowseActionExecutor : IActionExecutor +{ + public void Execute(BrowseAction action) + { + } +} \ No newline at end of file diff --git a/src/RepoM.Api/RepositoryActions/Executors/Delegate/DelegateActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/Delegate/DelegateActionExecutor.cs new file mode 100644 index 00000000..931a6f03 --- /dev/null +++ b/src/RepoM.Api/RepositoryActions/Executors/Delegate/DelegateActionExecutor.cs @@ -0,0 +1,19 @@ +namespace RepoM.Api.RepositoryActions.Executors.Delegate; + +using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.RepositoryActions.Actions; + +public class DelegateActionExecutor : IActionExecutor +{ + private DelegateActionExecutor() + { + } + + public static DelegateActionExecutor Instance { get; } = new DelegateActionExecutor(); + + + public void Execute(DelegateAction action) + { + action.Action.Invoke(null, null); + } +} \ No newline at end of file diff --git a/src/RepoM.Api/RepositoryActions/Executors/Null/NullActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/Null/NullActionExecutor.cs new file mode 100644 index 00000000..73090543 --- /dev/null +++ b/src/RepoM.Api/RepositoryActions/Executors/Null/NullActionExecutor.cs @@ -0,0 +1,12 @@ +namespace RepoM.Api.RepositoryActions.Executors.Null; + +using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.RepositoryActions.Actions; + +public class NullActionExecutor : IActionExecutor +{ + public void Execute(NullAction action) + { + return; + } +} \ No newline at end of file diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index 6ef0f88f..03d3e185 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -17,8 +17,10 @@ namespace RepoM.App; using RepoM.Api.Common; using RepoM.Api.Git; using RepoM.Api.IO; +using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.App.Controls; using RepoM.App.Services; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepoM.Core.Plugin.RepositoryOrdering; using SourceChord.FluentWPF; @@ -268,7 +270,10 @@ private void InvokeActionOnCurrentRepository() action = _repositoryActionProvider.GetPrimaryAction(selectedView.Repository); } - action?.Action?.Invoke(this, EventArgs.Empty); + if (action?.Action is DelegateAction da) + { + DelegateActionExecutor.Instance.Execute(da); + } } private void HelpButton_Click(object sender, RoutedEventArgs e) @@ -407,15 +412,23 @@ private void ShowUpdateIfAvailable() var coords = new float[] { 0, 0, }; // run actions in the UI async to not block it - if (repositoryAction.ExecutionCausesSynchronizing) + if (repositoryAction.Action is DelegateAction da) { - Task.Run(() => SetViewsSynchronizing(affectedViews, true)) - .ContinueWith(t => repositoryAction.Action(null, coords)) - .ContinueWith(t => SetViewsSynchronizing(affectedViews, false)); - } - else - { - Task.Run(() => repositoryAction.Action(null, coords)); + if (repositoryAction.ExecutionCausesSynchronizing) + { + Task.Run(() => SetViewsSynchronizing(affectedViews, true)) + .ContinueWith(t => DelegateActionExecutor.Instance.Execute(da)) //repositoryAction.Action(null, coords)) + .ContinueWith(t => SetViewsSynchronizing(affectedViews, false)); + } + else + { + + if (action?.Action != null) + { + // Task.Run(() => repositoryAction.Action(null, coords)); + Task.Run(() => DelegateActionExecutor.Instance.Execute(da)); + } + } } }; diff --git a/src/RepoM.Core.Plugin/RepositoryActions/Actions/BrowseAction.cs b/src/RepoM.Core.Plugin/RepositoryActions/Actions/BrowseAction.cs new file mode 100644 index 00000000..48920f0c --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryActions/Actions/BrowseAction.cs @@ -0,0 +1,7 @@ +namespace RepoM.Core.Plugin.RepositoryActions.Actions; + +using RepoM.Core.Plugin.RepositoryActions; + +public sealed class BrowseAction : IAction +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs b/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs new file mode 100644 index 00000000..6a12fb62 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs @@ -0,0 +1,14 @@ +namespace RepoM.Core.Plugin.RepositoryActions.Actions; + +using System; +using RepoM.Core.Plugin.RepositoryActions; + +public class DelegateAction : IAction +{ + public DelegateAction(Action? action) + { + Action = action; + } + + public Action Action { get; } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryActions/Actions/NullAction.cs b/src/RepoM.Core.Plugin/RepositoryActions/Actions/NullAction.cs new file mode 100644 index 00000000..019519f3 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryActions/Actions/NullAction.cs @@ -0,0 +1,12 @@ +namespace RepoM.Core.Plugin.RepositoryActions.Actions; + +using RepoM.Core.Plugin.RepositoryActions; + +public sealed class NullAction : IAction +{ + private NullAction() + { + } + + public static NullAction Instance { get; } = new NullAction(); +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryActions/IAction.cs b/src/RepoM.Core.Plugin/RepositoryActions/IAction.cs new file mode 100644 index 00000000..7e853a54 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryActions/IAction.cs @@ -0,0 +1,5 @@ +namespace RepoM.Core.Plugin.RepositoryActions; + +public interface IAction +{ +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs b/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs new file mode 100644 index 00000000..ef1798b9 --- /dev/null +++ b/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs @@ -0,0 +1,6 @@ +namespace RepoM.Core.Plugin.RepositoryActions; + +public interface IActionExecutor where T : IAction +{ + void Execute(T action); +} \ No newline at end of file diff --git a/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs b/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs index 0e55d471..812e1f91 100644 --- a/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs +++ b/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs @@ -11,6 +11,8 @@ namespace RepoM.Plugin.AzureDevOps; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; [UsedImplicitly] @@ -104,11 +106,11 @@ private Api.Git.RepositoryAction[] Map(RepositoryActionAzureDevOpsPullRequestsV1 var results = new List(pullRequests.Count); results.AddRange(pullRequests.Select(pr => new Api.Git.RepositoryAction(pr.Name) { - Action = (_, _) => + Action = new DelegateAction((_, _) => { _logger.LogInformation("PullRequest {Url}", pr.Url); ProcessHelper.StartProcess(pr.Url, string.Empty); - }, + }), })); return results.ToArray(); diff --git a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs index d31130b4..6fc1d871 100644 --- a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs +++ b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs @@ -10,6 +10,8 @@ namespace RepoM.Plugin.SonarCloud; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; +using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; [UsedImplicitly] @@ -65,7 +67,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository { yield return new Api.Git.RepositoryAction(name) { - Action = (_, _) => + Action = new DelegateAction((_, _) => { try { @@ -75,7 +77,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository { // ignore } - }, + }), ExecutionCausesSynchronizing = false, }; } From 3823231e6b1ee8c4c33cd26155b80ca71e4270b7 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sat, 26 Nov 2022 17:01:06 +0100 Subject: [PATCH 20/60] Moving implementations from plugin to api project --- .../ActionMappers/ActionAssociateFileV1Mapper.cs | 1 - .../ActionMappers/ActionBrowseRepositoryV1Mapper.cs | 1 - .../ActionMappers/ActionBrowserV1Mapper.cs | 1 - .../ActionMappers/ActionCommandV1Mapper.cs | 1 - .../ActionMappers/ActionExecutableV1Mapper.cs | 1 - .../ActionMappers/ActionGitCheckoutV1Mapper.cs | 1 - .../ActionMappers/ActionPinRepositoryV1Mapper.cs | 1 - .../RepositorySpecificConfiguration.cs | 1 - src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs | 1 - .../Ordering}/Az/AlphabetComparerConfigurationV1.cs | 2 +- .../Az/AlphabetComparerConfigurationV1Registration.cs | 2 +- .../Ordering}/Az/AzComparer.cs | 4 +++- .../Ordering}/Az/AzRepositoryComparerFactory.cs | 4 +++- .../Ordering}/Composition/CompositionComparer.cs | 4 +++- .../Composition/CompositionComparerConfigurationV1.cs | 2 +- .../CompositionComparerConfigurationV1Registration.cs | 2 +- .../CompositionRepositoryComparerFactory.cs | 3 ++- .../Ordering}/Label/TagScoreCalculator.cs | 4 +++- .../Ordering}/Label/TagScorerConfigurationV1.cs | 2 +- .../Label/TagScorerConfigurationV1Registration.cs | 2 +- .../Ordering}/Label/TagScorerFactory.cs | 3 ++- .../Ordering}/Score/ScoreComparer.cs | 4 +++- .../Ordering}/Score/ScoreComparerConfigurationV1.cs | 2 +- .../Score/ScoreComparerConfigurationV1Registration.cs | 2 +- .../Ordering}/Score/ScoreRepositoryComparerFactory.cs | 3 ++- .../Ordering}/Sum/SumComparerConfigurationV1.cs | 2 +- .../Sum/SumComparerConfigurationV1Registration.cs | 2 +- .../Ordering}/Sum/SumCompositionComparer.cs | 4 +++- .../Ordering}/Sum/SumRepositoryComparerFactory.cs | 3 ++- .../Executors/{Browse => }/BrowseActionExecutor.cs | 2 +- .../Executors/{Delegate => }/DelegateActionExecutor.cs | 2 +- .../Executors/{Null => }/NullActionExecutor.cs | 2 +- src/RepoM.App/App.xaml.cs | 10 +++++----- src/RepoM.App/MainWindow.xaml.cs | 2 +- .../ActionAzureDevOpsPullRequestsV1Mapper.cs | 1 - .../ActionSonarCloudV1Mapper.cs | 1 - tests/Yaml.Poc.Tests/DI/Bootstrapper.cs | 10 +++++----- tests/Yaml.Poc.Tests/YamlTests.cs | 6 +++--- 38 files changed, 53 insertions(+), 48 deletions(-) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Az/AlphabetComparerConfigurationV1.cs (76%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Az/AlphabetComparerConfigurationV1Registration.cs (81%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Az/AzComparer.cs (92%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Az/AzRepositoryComparerFactory.cs (78%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Composition/CompositionComparer.cs (86%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Composition/CompositionComparerConfigurationV1.cs (77%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Composition/CompositionComparerConfigurationV1Registration.cs (80%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Composition/CompositionRepositoryComparerFactory.cs (87%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Label/TagScoreCalculator.cs (78%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Label/TagScorerConfigurationV1.cs (74%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Label/TagScorerConfigurationV1Registration.cs (80%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Label/TagScorerFactory.cs (83%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Score/ScoreComparer.cs (86%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Score/ScoreComparerConfigurationV1.cs (75%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Score/ScoreComparerConfigurationV1Registration.cs (80%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Score/ScoreRepositoryComparerFactory.cs (87%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Sum/SumComparerConfigurationV1.cs (79%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Sum/SumComparerConfigurationV1Registration.cs (81%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Sum/SumCompositionComparer.cs (86%) rename src/{RepoM.Core.Plugin/RepositoryOrdering/Implementations => RepoM.Api/Ordering}/Sum/SumRepositoryComparerFactory.cs (87%) rename src/RepoM.Api/RepositoryActions/Executors/{Browse => }/BrowseActionExecutor.cs (79%) rename src/RepoM.Api/RepositoryActions/Executors/{Delegate => }/DelegateActionExecutor.cs (87%) rename src/RepoM.Api/RepositoryActions/Executors/{Null => }/NullActionExecutor.cs (81%) diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs index 99db40d1..1f26c3ad 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs @@ -8,7 +8,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs index 6ac772bc..0b7e78bf 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs @@ -7,7 +7,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; public class ActionBrowseRepositoryV1Mapper : IActionToRepositoryActionMapper diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs index bda03a8a..88eb6064 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs @@ -7,7 +7,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.Git.RepositoryAction; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs index 3d155f58..dea1e92a 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs @@ -7,7 +7,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs index daa8139e..e50376c9 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs @@ -8,7 +8,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs index 9fd07d06..3503023e 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs @@ -7,7 +7,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = Data.RepositoryAction; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs index 05af288e..1768b4c3 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs @@ -7,7 +7,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs index 684a71a5..04c0405e 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs @@ -16,7 +16,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Deserialization; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Exceptions; using RepoM.Api.IO.Variables; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using Repository = RepoM.Api.Git.Repository; using RepositoryAction = RepoM.Api.Git.RepositoryAction; diff --git a/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs b/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs index 51b06c7a..8584e22f 100644 --- a/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs +++ b/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs @@ -4,7 +4,6 @@ namespace RepoM.Api.IO; using System.Collections.Generic; using System.Linq; using RepoM.Api.Git; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; public static class MultipleRepositoryActionHelper diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1.cs b/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1.cs similarity index 76% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1.cs rename to src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1.cs index 4253396c..fc060a88 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1.cs +++ b/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +namespace RepoM.Api.Ordering.Az; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1Registration.cs similarity index 81% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1Registration.cs rename to src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1Registration.cs index e834ccbc..f24d3882 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AlphabetComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1Registration.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +namespace RepoM.Api.Ordering.Az; using System; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs b/src/RepoM.Api/Ordering/Az/AzComparer.cs similarity index 92% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs rename to src/RepoM.Api/Ordering/Az/AzComparer.cs index c60578be..749c72ae 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzComparer.cs +++ b/src/RepoM.Api/Ordering/Az/AzComparer.cs @@ -1,6 +1,8 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +namespace RepoM.Api.Ordering.Az; using System; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; public class AzComparer : IRepositoryComparer { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs b/src/RepoM.Api/Ordering/Az/AzRepositoryComparerFactory.cs similarity index 78% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs rename to src/RepoM.Api/Ordering/Az/AzRepositoryComparerFactory.cs index 4381514d..0e90121a 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Az/AzRepositoryComparerFactory.cs +++ b/src/RepoM.Api/Ordering/Az/AzRepositoryComparerFactory.cs @@ -1,4 +1,6 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; +namespace RepoM.Api.Ordering.Az; + +using RepoM.Core.Plugin.RepositoryOrdering; public class AzRepositoryComparerFactory : IRepositoryComparerFactory { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparer.cs b/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs similarity index 86% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparer.cs rename to src/RepoM.Api/Ordering/Composition/CompositionComparer.cs index cc8a0bb3..5a0e0140 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparer.cs +++ b/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs @@ -1,7 +1,9 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; +namespace RepoM.Api.Ordering.Composition; using System.Collections.Generic; using System.Linq; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; public class CompositionComparer : IRepositoryComparer { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1.cs b/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1.cs similarity index 77% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1.cs rename to src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1.cs index c5cb49c7..3069717a 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1.cs +++ b/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; +namespace RepoM.Api.Ordering.Composition; using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1Registration.cs similarity index 80% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs rename to src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1Registration.cs index 10cdd316..959317ea 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1Registration.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; +namespace RepoM.Api.Ordering.Composition; using System; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs b/src/RepoM.Api/Ordering/Composition/CompositionRepositoryComparerFactory.cs similarity index 87% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs rename to src/RepoM.Api/Ordering/Composition/CompositionRepositoryComparerFactory.cs index 2c6ff892..5ae40434 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Composition/CompositionRepositoryComparerFactory.cs +++ b/src/RepoM.Api/Ordering/Composition/CompositionRepositoryComparerFactory.cs @@ -1,7 +1,8 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; +namespace RepoM.Api.Ordering.Composition; using System; using System.Linq; +using RepoM.Core.Plugin.RepositoryOrdering; public class CompositionRepositoryComparerFactory : IRepositoryComparerFactory { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScoreCalculator.cs b/src/RepoM.Api/Ordering/Label/TagScoreCalculator.cs similarity index 78% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScoreCalculator.cs rename to src/RepoM.Api/Ordering/Label/TagScoreCalculator.cs index b71eaef7..b886704c 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScoreCalculator.cs +++ b/src/RepoM.Api/Ordering/Label/TagScoreCalculator.cs @@ -1,6 +1,8 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +namespace RepoM.Api.Ordering.Label; using System.Linq; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; public class TagScoreCalculator : IRepositoryScoreCalculator { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1.cs b/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1.cs similarity index 74% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1.cs rename to src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1.cs index 6e7f98d3..8b6efb7d 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1.cs +++ b/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +namespace RepoM.Api.Ordering.Label; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1Registration.cs similarity index 80% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1Registration.cs rename to src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1Registration.cs index 243d3ab0..14826361 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1Registration.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +namespace RepoM.Api.Ordering.Label; using System; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerFactory.cs b/src/RepoM.Api/Ordering/Label/TagScorerFactory.cs similarity index 83% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerFactory.cs rename to src/RepoM.Api/Ordering/Label/TagScorerFactory.cs index e7ac1f81..e2491fb3 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Label/TagScorerFactory.cs +++ b/src/RepoM.Api/Ordering/Label/TagScorerFactory.cs @@ -1,6 +1,7 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; +namespace RepoM.Api.Ordering.Label; using System; +using RepoM.Core.Plugin.RepositoryOrdering; public class TagScorerFactory : IRepositoryScoreCalculatorFactory { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs b/src/RepoM.Api/Ordering/Score/ScoreComparer.cs similarity index 86% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs rename to src/RepoM.Api/Ordering/Score/ScoreComparer.cs index 67f01f83..251b6460 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparer.cs +++ b/src/RepoM.Api/Ordering/Score/ScoreComparer.cs @@ -1,6 +1,8 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; +namespace RepoM.Api.Ordering.Score; using System; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; public class ScoreComparer : IRepositoryComparer { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs b/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1.cs similarity index 75% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs rename to src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1.cs index 3df86a41..ca29177f 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1.cs +++ b/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; +namespace RepoM.Api.Ordering.Score; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1Registration.cs similarity index 80% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs rename to src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1Registration.cs index c82c15b5..3decb149 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1Registration.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; +namespace RepoM.Api.Ordering.Score; using System; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs b/src/RepoM.Api/Ordering/Score/ScoreRepositoryComparerFactory.cs similarity index 87% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs rename to src/RepoM.Api/Ordering/Score/ScoreRepositoryComparerFactory.cs index bc56c03d..afaaf629 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Score/ScoreRepositoryComparerFactory.cs +++ b/src/RepoM.Api/Ordering/Score/ScoreRepositoryComparerFactory.cs @@ -1,6 +1,7 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; +namespace RepoM.Api.Ordering.Score; using System; +using RepoM.Core.Plugin.RepositoryOrdering; public class ScoreRepositoryComparerFactory : IRepositoryComparerFactory { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs b/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1.cs similarity index 79% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs rename to src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1.cs index 297c48d9..3b0911d2 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1.cs +++ b/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; +namespace RepoM.Api.Ordering.Sum; using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1Registration.cs similarity index 81% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs rename to src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1Registration.cs index df2f74a2..8c31f259 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1Registration.cs @@ -1,4 +1,4 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; +namespace RepoM.Api.Ordering.Sum; using System; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs b/src/RepoM.Api/Ordering/Sum/SumCompositionComparer.cs similarity index 86% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs rename to src/RepoM.Api/Ordering/Sum/SumCompositionComparer.cs index e7f163dc..717d719d 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumCompositionComparer.cs +++ b/src/RepoM.Api/Ordering/Sum/SumCompositionComparer.cs @@ -1,7 +1,9 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; +namespace RepoM.Api.Ordering.Sum; using System.Collections.Generic; using System.Linq; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; public class SumCompositionComparer : IRepositoryComparer { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs b/src/RepoM.Api/Ordering/Sum/SumRepositoryComparerFactory.cs similarity index 87% rename from src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs rename to src/RepoM.Api/Ordering/Sum/SumRepositoryComparerFactory.cs index 1b5d7526..1aed0fe6 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/Implementations/Sum/SumRepositoryComparerFactory.cs +++ b/src/RepoM.Api/Ordering/Sum/SumRepositoryComparerFactory.cs @@ -1,7 +1,8 @@ -namespace RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; +namespace RepoM.Api.Ordering.Sum; using System; using System.Linq; +using RepoM.Core.Plugin.RepositoryOrdering; public class SumRepositoryComparerFactory : IRepositoryComparerFactory { diff --git a/src/RepoM.Api/RepositoryActions/Executors/Browse/BrowseActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs similarity index 79% rename from src/RepoM.Api/RepositoryActions/Executors/Browse/BrowseActionExecutor.cs rename to src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs index c2e6dc61..c531d139 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/Browse/BrowseActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs @@ -1,4 +1,4 @@ -namespace RepoM.Api.RepositoryActions.Executors.Browse; +namespace RepoM.Api.RepositoryActions.Executors; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; diff --git a/src/RepoM.Api/RepositoryActions/Executors/Delegate/DelegateActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs similarity index 87% rename from src/RepoM.Api/RepositoryActions/Executors/Delegate/DelegateActionExecutor.cs rename to src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs index 931a6f03..e1bf2637 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/Delegate/DelegateActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs @@ -1,4 +1,4 @@ -namespace RepoM.Api.RepositoryActions.Executors.Delegate; +namespace RepoM.Api.RepositoryActions.Executors; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; diff --git a/src/RepoM.Api/RepositoryActions/Executors/Null/NullActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs similarity index 81% rename from src/RepoM.Api/RepositoryActions/Executors/Null/NullActionExecutor.cs rename to src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs index 73090543..fff473c7 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/Null/NullActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs @@ -1,4 +1,4 @@ -namespace RepoM.Api.RepositoryActions.Executors.Null; +namespace RepoM.Api.RepositoryActions.Executors; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index ca7e576a..0b781fb7 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -37,13 +37,13 @@ namespace RepoM.App; using RepoM.Api.IO.VariableProviders; using RepoM.Api.Ordering.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using RepoM.Core.Plugin.RepositoryOrdering; using System.ComponentModel; +using RepoM.Api.Ordering.Az; +using RepoM.Api.Ordering.Composition; +using RepoM.Api.Ordering.Label; +using RepoM.Api.Ordering.Score; +using RepoM.Api.Ordering.Sum; using Container = SimpleInjector.Container; internal class RepositoryComparerCompositionFactory : IRepositoryComparerFactory diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index 03d3e185..454c61fe 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -17,7 +17,7 @@ namespace RepoM.App; using RepoM.Api.Common; using RepoM.Api.Git; using RepoM.Api.IO; -using RepoM.Api.RepositoryActions.Executors.Delegate; +using RepoM.Api.RepositoryActions.Executors; using RepoM.App.Controls; using RepoM.App.Services; using RepoM.Core.Plugin.RepositoryActions.Actions; diff --git a/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs b/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs index 812e1f91..6df2f893 100644 --- a/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs +++ b/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs @@ -11,7 +11,6 @@ namespace RepoM.Plugin.AzureDevOps; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; diff --git a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs index 6fc1d871..4c656a20 100644 --- a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs +++ b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs @@ -10,7 +10,6 @@ namespace RepoM.Plugin.SonarCloud; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; -using RepoM.Api.RepositoryActions.Executors.Delegate; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; diff --git a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs index ad1643b1..bdf1829c 100644 --- a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs +++ b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs @@ -3,14 +3,14 @@ namespace Yaml.Poc.Tests.DI; using System; using System.Threading.Tasks; using RepoM.Api.Git; +using RepoM.Api.Ordering.Az; +using RepoM.Api.Ordering.Composition; using RepoM.Api.Ordering.IsPinned; +using RepoM.Api.Ordering.Label; +using RepoM.Api.Ordering.Score; +using RepoM.Api.Ordering.Sum; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Composition; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Label; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using SimpleInjector; using Container = SimpleInjector.Container; diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index 693b97c3..7da425a0 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -3,13 +3,13 @@ namespace Yaml.Poc.Tests; using System; using System.Collections.Generic; using System.Threading.Tasks; +using RepoM.Api.Ordering.Az; using RepoM.Api.Ordering.IsPinned; +using RepoM.Api.Ordering.Score; +using RepoM.Api.Ordering.Sum; using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Az; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Score; -using RepoM.Core.Plugin.RepositoryOrdering.Implementations.Sum; using SimpleInjector; using VerifyXunit; using Xunit; From c1e2055b220e804a24e7431fbcf4a154de29a466 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sat, 26 Nov 2022 17:03:01 +0100 Subject: [PATCH 21/60] . --- .../RepositoryActions/Actions/DelegateAction.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs b/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs index 6a12fb62..72abe43f 100644 --- a/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs +++ b/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs @@ -3,11 +3,11 @@ namespace RepoM.Core.Plugin.RepositoryActions.Actions; using System; using RepoM.Core.Plugin.RepositoryActions; -public class DelegateAction : IAction +public sealed class DelegateAction : IAction { - public DelegateAction(Action? action) + public DelegateAction(Action action) { - Action = action; + Action = action ?? throw new ArgumentNullException(nameof(action)); } public Action Action { get; } From 9bffd18c32915a9ab8ffc56ef524ae4a5c096bf5 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sat, 26 Nov 2022 17:19:22 +0100 Subject: [PATCH 22/60] WIP --- src/RepoM.Api/Git/RepositoryAction.cs | 15 ++++++++++++++- .../ActionAssociateFileV1Mapper.cs | 9 +++++---- .../ActionBrowseRepositoryV1Mapper.cs | 11 ++++++----- .../ActionMappers/ActionBrowserV1Mapper.cs | 2 +- .../ActionMappers/ActionCommandV1Mapper.cs | 2 +- .../ActionMappers/ActionExecutableV1Mapper.cs | 2 +- .../ActionMappers/ActionFolderV1Mapper.cs | 4 ++-- .../ActionMappers/ActionGitCheckoutV1Mapper.cs | 14 +++++++------- .../ActionPinRepositoryV1Mapper.cs | 2 +- .../ActionMappers/ActionSeparatorV1Mapper.cs | 2 +- .../RepositorySpecificConfiguration.cs | 15 +++++++++------ .../IO/MultipleRepositoryActionHelper.cs | 3 ++- .../Decorators/LoggerActionExecutorDecorator.cs | 5 +++-- .../Executors/BrowseActionExecutor.cs | 5 ++++- .../Executors/DelegateActionExecutor.cs | 3 ++- .../Executors/NullActionExecutor.cs | 3 ++- src/RepoM.App/MainWindow.xaml.cs | 17 ++++++++--------- .../RepositoryActions/IActionExecutor.cs | 2 +- .../ActionAzureDevOpsPullRequestsV1Mapper.cs | 6 +++--- .../ActionSonarCloudV1Mapper.cs | 4 ++-- 20 files changed, 75 insertions(+), 51 deletions(-) diff --git a/src/RepoM.Api/Git/RepositoryAction.cs b/src/RepoM.Api/Git/RepositoryAction.cs index 0fec110e..156bd15a 100644 --- a/src/RepoM.Api/Git/RepositoryAction.cs +++ b/src/RepoM.Api/Git/RepositoryAction.cs @@ -2,17 +2,23 @@ namespace RepoM.Api.Git; using System; using System.Collections.Generic; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; public class RepositorySeparatorAction : RepositoryActionBase { + public RepositorySeparatorAction(IRepository repository) + : base(repository) + { + } } public class RepositoryAction : RepositoryActionBase { - public RepositoryAction(string name) + public RepositoryAction(string name, IRepository repository): + base(repository) { Name = name; } @@ -22,8 +28,15 @@ public RepositoryAction(string name) public abstract class RepositoryActionBase { + public RepositoryActionBase(IRepository repository) + { + Repository = repository ?? throw new ArgumentNullException(nameof(repository)); + } + public IAction Action { get; set; } = NullAction.Instance; + public IRepository Repository { get; } + public bool ExecutionCausesSynchronizing { get; set; } public bool CanExecute { get; set; } = true; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs index 1f26c3ad..6f2bed70 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs @@ -8,6 +8,7 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; @@ -71,9 +72,9 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository } } - private Git.RepositoryAction CreateProcessRunnerAction(string name, string process, string arguments = "") + private static Git.RepositoryAction CreateProcessRunnerAction(string name, string process, IRepository repository, string arguments = "") { - return new Git.RepositoryAction(name) + return new Git.RepositoryAction(name, repository) { Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(process, arguments)), }; @@ -86,11 +87,11 @@ private Git.RepositoryAction CreateProcessRunnerAction(string name, string proce return null; } - return new RepoM.Api.Git.RepositoryAction(actionName) + return new RepoM.Api.Git.RepositoryAction(actionName, repository) { DeferredSubActionsEnumerator = () => GetFiles(repository, filePattern) - .Select(solutionFile => CreateProcessRunnerAction(Path.GetFileName(solutionFile), solutionFile)) + .Select(solutionFile => CreateProcessRunnerAction(Path.GetFileName(solutionFile), solutionFile, repository)) .ToArray(), }; } diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs index 0b7e78bf..a75db609 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs @@ -7,6 +7,7 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions.Actions; public class ActionBrowseRepositoryV1Mapper : IActionToRepositoryActionMapper @@ -71,21 +72,21 @@ private IEnumerable Map(RepositoryActionBrowseRepositoryV1? ac if (repository.Remotes.Count == 1 || forceSingle) { - return CreateProcessRunnerAction(actionName, repository.Remotes[0].Url); + return CreateProcessRunnerAction(actionName, repository.Remotes[0].Url, repository); } - return new RepositoryAction(actionName) + return new RepositoryAction(actionName, repository) { DeferredSubActionsEnumerator = () => repository.Remotes .Take(50) - .Select(remote => CreateProcessRunnerAction(remote.Name, remote.Url)) + .Select(remote => CreateProcessRunnerAction(remote.Name, remote.Url, repository)) .ToArray(), }; } - private static RepositoryAction CreateProcessRunnerAction(string name, string process, string arguments = "") + private static RepositoryAction CreateProcessRunnerAction(string name, string process, IRepository repository, string arguments = "") { - return new RepositoryAction(name) + return new RepositoryAction(name, repository) { Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(process, arguments)), }; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs index 88eb6064..dbb0b082 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowserV1Mapper.cs @@ -55,7 +55,7 @@ private IEnumerable Map(RepositoryActionBrowserV1? action, Rep var name = NameHelper.EvaluateName(action.Name, repository, _translationService, _expressionEvaluator); var url = _expressionEvaluator.EvaluateStringExpression(action.Url, repository); - yield return new RepositoryAction(name) + yield return new RepositoryAction(name, repository) { Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(url, string.Empty)), }; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs index dea1e92a..0d2622b7 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionCommandV1Mapper.cs @@ -52,7 +52,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository var command = _expressionEvaluator.EvaluateStringExpression(action.Command ?? string.Empty, repository); var arguments = _expressionEvaluator.EvaluateStringExpression(action.Arguments ?? string.Empty, repository); - yield return new Git.RepositoryAction(name) + yield return new Git.RepositoryAction(name, repository) { Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(command, arguments)), }; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs index e50376c9..e4a8b810 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionExecutableV1Mapper.cs @@ -77,7 +77,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository arguments = _expressionEvaluator.EvaluateStringExpression(action.Arguments, repository); } - yield return new Git.RepositoryAction(name) + yield return new Git.RepositoryAction(name, repository) { Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(normalized, arguments)) }; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionFolderV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionFolderV1Mapper.cs index 6cf0d938..c423824c 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionFolderV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionFolderV1Mapper.cs @@ -57,7 +57,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository if (deferred) { - yield return new RepoM.Api.Git.RepositoryAction(name) + yield return new RepoM.Api.Git.RepositoryAction(name, repository) { CanExecute = true, DeferredSubActionsEnumerator = () => @@ -69,7 +69,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository } else { - yield return new RepoM.Api.Git.RepositoryAction(name) + yield return new RepoM.Api.Git.RepositoryAction(name, repository) { CanExecute = true, SubActions = action.Items diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs index 3503023e..052b69e0 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionGitCheckoutV1Mapper.cs @@ -61,26 +61,26 @@ private IEnumerable Map(RepositoryActionGitCheckoutV1? act name = _translationService.Translate("Checkout"); } - yield return new Git.RepositoryAction(_translationService.Translate("Checkout")) + yield return new Git.RepositoryAction(_translationService.Translate("Checkout"), repository) { DeferredSubActionsEnumerator = () => repository.LocalBranches .Take(50) - .Select(branch => new Git.RepositoryAction(branch) + .Select(branch => new Git.RepositoryAction(branch, repository) { Action = new DelegateAction((_, _) => _repositoryWriter.Checkout(repository, branch)), CanExecute = !repository.CurrentBranch.Equals(branch, StringComparison.OrdinalIgnoreCase), }) .Union(new RepositoryActionBase[] { - new RepositorySeparatorAction(), // doesn't work todo - new Git.RepositoryAction(_translationService.Translate("Remote branches")) + new RepositorySeparatorAction(repository), // doesn't work todo + new Git.RepositoryAction(_translationService.Translate("Remote branches"), repository) { DeferredSubActionsEnumerator = () => { Git.RepositoryAction[] remoteBranches = repository .ReadAllBranches() - .Select(branch => new Git.RepositoryAction(branch) + .Select(branch => new Git.RepositoryAction(branch, repository) { Action = new DelegateAction((_, _) => _repositoryWriter.Checkout(repository, branch)), CanExecute = !repository.CurrentBranch.Equals(branch, StringComparison.OrdinalIgnoreCase), @@ -94,11 +94,11 @@ private IEnumerable Map(RepositoryActionGitCheckoutV1? act return new RepositoryActionBase[] { - new Git.RepositoryAction(_translationService.Translate("No remote branches found")) + new Git.RepositoryAction(_translationService.Translate("No remote branches found"), repository) { CanExecute = false, }, - new Git.RepositoryAction(_translationService.Translate("Try to fetch changes if you're expecting remote branches")) + new Git.RepositoryAction(_translationService.Translate("Try to fetch changes if you're expecting remote branches"), repository) { CanExecute = false, }, diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs index 1768b4c3..5f8a1121 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionPinRepositoryV1Mapper.cs @@ -86,7 +86,7 @@ private IEnumerable Map(RepositoryActionPinRepositoryV1? a Git.RepositoryAction CreateAction(string name, Repository repository, bool newPinnedValue) { - return new Git.RepositoryAction(name) + return new Git.RepositoryAction(name, repository) { Action = new DelegateAction((_, _) => _repositoryMonitor.SetPinned(newPinnedValue, repository)), }; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionSeparatorV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionSeparatorV1Mapper.cs index 5c0cd747..74122548 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionSeparatorV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionSeparatorV1Mapper.cs @@ -53,6 +53,6 @@ private IEnumerable Map(RepositoryActionSeparatorV1? actio yield break; } - yield return new RepositorySeparatorAction(); + yield return new RepositorySeparatorAction(repository); } } \ No newline at end of file diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs index 04c0405e..33c597d9 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs @@ -7,6 +7,7 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using System.Linq; using System.Text; using DotNetEnv; +using LibGit2Sharp; using Microsoft.Extensions.Logging; using RepoM.Api.Common; using RepoM.Api.Git; @@ -16,7 +17,9 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Deserialization; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Exceptions; using RepoM.Api.IO.Variables; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions.Actions; +using IRepository = RepoM.Core.Plugin.IRepository; using Repository = RepoM.Api.Git.Repository; using RepositoryAction = RepoM.Api.Git.RepositoryAction; @@ -446,14 +449,14 @@ public IEnumerable CreateActions(params Repository[] repos { if (ex is ConfigurationFileNotFoundException configurationFileNotFoundException) { - foreach (RepositoryAction failingItem in CreateFailing(configurationFileNotFoundException, configurationFileNotFoundException.Filename)) + foreach (RepositoryAction failingItem in CreateFailing(configurationFileNotFoundException, configurationFileNotFoundException.Filename, singleRepository!)) // todo coenm { yield return failingItem; } } else { - foreach (RepositoryAction failingItem in CreateFailing(ex, null)) + foreach (RepositoryAction failingItem in CreateFailing(ex, null, singleRepository!)) // todo coenm { yield return failingItem; } @@ -510,21 +513,21 @@ private List EvaluateVariables(IEnumerable? vars, R .ToList(); } - private IEnumerable CreateFailing(Exception ex, string? filename) + private IEnumerable CreateFailing(Exception ex, string? filename, IRepository repository) { - yield return new RepositoryAction(_translationService.Translate("Could not read repository actions")) + yield return new RepositoryAction(_translationService.Translate("Could not read repository actions"), repository) { CanExecute = false, }; - yield return new RepositoryAction(ex.Message) + yield return new RepositoryAction(ex.Message, repository) { CanExecute = false, }; if (!string.IsNullOrWhiteSpace(filename)) { - yield return new RepositoryAction(_translationService.Translate("Fix")) + yield return new RepositoryAction(_translationService.Translate("Fix"), repository) { Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(_fileSystem.Path.GetDirectoryName(filename), string.Empty)), }; diff --git a/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs b/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs index 8584e22f..06260fce 100644 --- a/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs +++ b/src/RepoM.Api/IO/MultipleRepositoryActionHelper.cs @@ -14,7 +14,8 @@ public static RepositoryAction CreateActionForMultipleRepositories( Action action, bool executionCausesSynchronizing = false) { - return new RepositoryAction(name) + // todo coen, fix + return new RepositoryAction(name, repositories.First()) { Action = new DelegateAction((_, _) => { diff --git a/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs b/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs index 6ee7a424..163aed7f 100644 --- a/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs +++ b/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs @@ -1,5 +1,6 @@ namespace RepoM.Api.RepositoryActions.Decorators; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions; public class LoggerActionExecutorDecorator : IActionExecutor where T : IAction @@ -11,8 +12,8 @@ public LoggerActionExecutorDecorator(IActionExecutor decoratee) _decoratee = decoratee; } - public void Execute(T action) + public void Execute(IRepository repository, T action) { - _decoratee.Execute(action); + _decoratee.Execute(repository, action); } } \ No newline at end of file diff --git a/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs index c531d139..6984fec4 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs @@ -1,11 +1,14 @@ namespace RepoM.Api.RepositoryActions.Executors; +using System; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; public class BrowseActionExecutor : IActionExecutor { - public void Execute(BrowseAction action) + public void Execute(IRepository repository, BrowseAction action) { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs index e1bf2637..3af6f804 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs @@ -1,5 +1,6 @@ namespace RepoM.Api.RepositoryActions.Executors; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; @@ -12,7 +13,7 @@ private DelegateActionExecutor() public static DelegateActionExecutor Instance { get; } = new DelegateActionExecutor(); - public void Execute(DelegateAction action) + public void Execute(IRepository repository, DelegateAction action) { action.Action.Invoke(null, null); } diff --git a/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs index fff473c7..c631e668 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs @@ -1,11 +1,12 @@ namespace RepoM.Api.RepositoryActions.Executors; +using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; public class NullActionExecutor : IActionExecutor { - public void Execute(NullAction action) + public void Execute(IRepository repository, NullAction action) { return; } diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index 454c61fe..f3821775 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -272,7 +272,7 @@ private void InvokeActionOnCurrentRepository() if (action?.Action is DelegateAction da) { - DelegateActionExecutor.Instance.Execute(da); + DelegateActionExecutor.Instance.Execute(action.Repository, da); } } @@ -410,26 +410,25 @@ private void ShowUpdateIfAvailable() } var coords = new float[] { 0, 0, }; - + // run actions in the UI async to not block it if (repositoryAction.Action is DelegateAction da) { if (repositoryAction.ExecutionCausesSynchronizing) { Task.Run(() => SetViewsSynchronizing(affectedViews, true)) - .ContinueWith(t => DelegateActionExecutor.Instance.Execute(da)) //repositoryAction.Action(null, coords)) + .ContinueWith(t => DelegateActionExecutor.Instance.Execute(repositoryAction.Repository, da)) //repositoryAction.Action(null, coords)) .ContinueWith(t => SetViewsSynchronizing(affectedViews, false)); } else { - - if (action?.Action != null) - { - // Task.Run(() => repositoryAction.Action(null, coords)); - Task.Run(() => DelegateActionExecutor.Instance.Execute(da)); - } + Task.Run(() => DelegateActionExecutor.Instance.Execute(repositoryAction.Repository, da)); } } + else + { + throw new NotImplementedException(); + } }; var item = new AcrylicMenuItem diff --git a/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs b/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs index ef1798b9..f301a81f 100644 --- a/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs +++ b/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs @@ -2,5 +2,5 @@ namespace RepoM.Core.Plugin.RepositoryActions; public interface IActionExecutor where T : IAction { - void Execute(T action); + void Execute(IRepository repository, T action); } \ No newline at end of file diff --git a/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs b/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs index 6df2f893..cb13c614 100644 --- a/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs +++ b/src/RepoM.Plugin.AzureDevOps/ActionAzureDevOpsPullRequestsV1Mapper.cs @@ -92,7 +92,7 @@ private Api.Git.RepositoryAction[] Map(RepositoryActionAzureDevOpsPullRequestsV1 } catch (Exception e) { - var notificationItem = new Api.Git.RepositoryAction($"An error occurred grabbing pull requests. {e.Message}") + var notificationItem = new Api.Git.RepositoryAction($"An error occurred grabbing pull requests. {e.Message}", repository) { CanExecute = false, ExecutionCausesSynchronizing = false, @@ -103,7 +103,7 @@ private Api.Git.RepositoryAction[] Map(RepositoryActionAzureDevOpsPullRequestsV1 if (pullRequests.Any()) { var results = new List(pullRequests.Count); - results.AddRange(pullRequests.Select(pr => new Api.Git.RepositoryAction(pr.Name) + results.AddRange(pullRequests.Select(pr => new Api.Git.RepositoryAction(pr.Name, repository) { Action = new DelegateAction((_, _) => { @@ -119,7 +119,7 @@ private Api.Git.RepositoryAction[] Map(RepositoryActionAzureDevOpsPullRequestsV1 // check if user wants a notification if (_expressionEvaluator.EvaluateBooleanExpression(action.ShowWhenEmpty, repository)) { - var notificationItem = new Api.Git.RepositoryAction("No PRs found.") + var notificationItem = new Api.Git.RepositoryAction("No PRs found.", repository) { CanExecute = false, ExecutionCausesSynchronizing = false, diff --git a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs index 4c656a20..57f8349b 100644 --- a/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs +++ b/src/RepoM.Plugin.SonarCloud/ActionSonarCloudV1Mapper.cs @@ -64,7 +64,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository if (_service.IsInitialized) { - yield return new Api.Git.RepositoryAction(name) + yield return new Api.Git.RepositoryAction(name, repository) { Action = new DelegateAction((_, _) => { @@ -82,7 +82,7 @@ IEnumerable IActionToRepositoryActionMapper.Map(Repository } else { - yield return new Api.Git.RepositoryAction(name) + yield return new Api.Git.RepositoryAction(name, repository) { CanExecute = false, }; From 5678aad5708904f92089526e549d264f8b44145c Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sat, 26 Nov 2022 18:58:53 +0100 Subject: [PATCH 23/60] fixing tests --- .../RepositorySpecificConfigurationTest.cs | 1 + ...ltiSelectRepos_WhenSingleRepo.verified.txt | 36 ++++++++++++------- ...reate_ShouldProcessSeparator1.verified.txt | 21 +++++++---- ...ShouldRespectMultiSelectRepos.verified.txt | 18 ++++++---- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs index 37c02425..76aa27c3 100644 --- a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs @@ -54,6 +54,7 @@ public RepositorySpecificConfigurationTest() _verifySettings = new VerifySettings(); _verifySettings.UseDirectory("Verified"); + _verifySettings.IgnoreMember(nameof(Repository)); _tempPath = Path.GetTempPath(); _fileSystem = new MockFileSystem(new Dictionary(), "C:\\"); diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldNotCareAboutMultiSelectRepos_WhenSingleRepo.verified.txt b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldNotCareAboutMultiSelectRepos_WhenSingleRepo.verified.txt index 89737932..fc7fe337 100644 --- a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldNotCareAboutMultiSelectRepos_WhenSingleRepo.verified.txt +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldNotCareAboutMultiSelectRepos_WhenSingleRepo.verified.txt @@ -3,9 +3,12 @@ $type: RepositoryAction, Name: Google 1, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true @@ -14,9 +17,12 @@ $type: RepositoryAction, Name: Google 2, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true @@ -25,9 +31,12 @@ $type: RepositoryAction, Name: Google 4, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true @@ -36,9 +45,12 @@ $type: RepositoryAction, Name: Google 5, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldProcessSeparator1.verified.txt b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldProcessSeparator1.verified.txt index b87b773a..442ed10f 100644 --- a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldProcessSeparator1.verified.txt +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldProcessSeparator1.verified.txt @@ -3,15 +3,21 @@ $type: RepositoryAction, Name: Google 1, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true }, { $type: RepositorySeparatorAction, + Action: { + $type: NullAction + }, ExecutionCausesSynchronizing: false, CanExecute: true }, @@ -19,9 +25,12 @@ $type: RepositoryAction, Name: Google 2, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldRespectMultiSelectRepos.verified.txt b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldRespectMultiSelectRepos.verified.txt index 3d23caf4..a1bd0df9 100644 --- a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldRespectMultiSelectRepos.verified.txt +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Verified/RepositorySpecificConfigurationTest.Create_ShouldRespectMultiSelectRepos.verified.txt @@ -3,9 +3,12 @@ $type: RepositoryAction, Name: Google 1, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true @@ -14,9 +17,12 @@ $type: RepositoryAction, Name: Google 5, Action: { - Type: Action, - Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, - Method: Void Map(System.Object, System.Object) + $type: DelegateAction, + Action: { + Type: Action, + Target: ActionBrowserV1Mapper.<>c__DisplayClass6_0, + Method: Void Map(System.Object, System.Object) + } }, ExecutionCausesSynchronizing: false, CanExecute: true From 5db6ed9f18456fa61e0bcc1554b36c0363ed394a Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sat, 26 Nov 2022 19:35:11 +0100 Subject: [PATCH 24/60] Add module mvp --- RepoM.sln | 23 ++++++++++++ src/RepoM.App/RepoM.App.csproj | 1 + .../Ordering/UsageScoreCalculator.cs | 22 +++++++++++ .../Ordering/UsageScorerConfigurationV1.cs | 7 ++++ .../UsageScorerConfigurationV1Registration.cs | 13 +++++++ .../Ordering/UsageScorerFactory.cs | 20 ++++++++++ .../RepoM.Plugin.Statistics.csproj | 18 +++++++++ ...RecordStatisticsActionExecutorDecorator.cs | 37 +++++++++++++++++++ .../StatisticsModule.cs | 28 ++++++++++++++ .../StatisticsPackage.cs | 35 ++++++++++++++++++ .../StatisticsService.cs | 33 +++++++++++++++++ 11 files changed, 237 insertions(+) create mode 100644 src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs create mode 100644 src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj create mode 100644 src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs create mode 100644 src/RepoM.Plugin.Statistics/StatisticsModule.cs create mode 100644 src/RepoM.Plugin.Statistics/StatisticsPackage.cs create mode 100644 src/RepoM.Plugin.Statistics/StatisticsService.cs diff --git a/RepoM.sln b/RepoM.sln index fbf46806..1d707d56 100644 --- a/RepoM.sln +++ b/RepoM.sln @@ -35,6 +35,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Core.Plugin", "src\Re EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yaml.Poc.Tests", "tests\Yaml.Poc.Tests\Yaml.Poc.Tests.csproj", "{C5A65FD2-CD65-47EA-A521-8B7C756AC986}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.Statistics", "src\RepoM.Plugin.Statistics\RepoM.Plugin.Statistics.csproj", "{DF4F5FA8-0E3F-4D84-A048-20242FD032BC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -349,6 +351,26 @@ Global {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x64.Build.0 = Release|Any CPU {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x86.ActiveCfg = Release|Any CPU {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x86.Build.0 = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|ARM.ActiveCfg = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|ARM.Build.0 = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|ARM64.Build.0 = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|x64.ActiveCfg = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|x64.Build.0 = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|x86.ActiveCfg = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|x86.Build.0 = Debug|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|Any CPU.Build.0 = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|ARM.ActiveCfg = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|ARM.Build.0 = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|ARM64.ActiveCfg = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|ARM64.Build.0 = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|x64.ActiveCfg = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|x64.Build.0 = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|x86.ActiveCfg = Release|Any CPU + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -362,6 +384,7 @@ Global {74B95BAF-0DB4-42C8-92EA-A364E8080809} = {D6E372DC-10D3-4997-9DFC-568B4666635A} {26FF9590-66C7-4B87-9574-E816E1E36628} = {D6E372DC-10D3-4997-9DFC-568B4666635A} {C2014EE2-F17C-478E-B282-9D0971065BB8} = {D6E372DC-10D3-4997-9DFC-568B4666635A} + {DF4F5FA8-0E3F-4D84-A048-20242FD032BC} = {D6E372DC-10D3-4997-9DFC-568B4666635A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1765ABAA-0652-4DA5-ABBF-05396F2957D7} diff --git a/src/RepoM.App/RepoM.App.csproj b/src/RepoM.App/RepoM.App.csproj index 6f62f75f..ab80b466 100644 --- a/src/RepoM.App/RepoM.App.csproj +++ b/src/RepoM.App/RepoM.App.csproj @@ -25,6 +25,7 @@ + diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs new file mode 100644 index 00000000..4f866da9 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs @@ -0,0 +1,22 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System; +using System.Collections.Generic; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryOrdering; + +internal class UsageScoreCalculator : IRepositoryScoreCalculator +{ + private readonly StatisticsService _service; + + public UsageScoreCalculator(StatisticsService service) + { + _service = service ?? throw new ArgumentNullException(nameof(service)); + } + + public int Score(IRepository repository) + { + IReadOnlyList recordings = _service.GetRecordings(repository); + return recordings.Count; + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs new file mode 100644 index 00000000..5e7acc77 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs @@ -0,0 +1,7 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public class UsageScorerConfigurationV1 : IRepositoryScorerConfiguration +{ +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs new file mode 100644 index 00000000..d0c5a517 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs @@ -0,0 +1,13 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System; +using JetBrains.Annotations; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +[UsedImplicitly] +public class UsageScorerConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(UsageScorerConfigurationV1); + + public string Tag { get; } = "usage@1"; +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs new file mode 100644 index 00000000..4b220be3 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs @@ -0,0 +1,20 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System; +using RepoM.Api.Git; +using RepoM.Core.Plugin.RepositoryOrdering; + +internal class UsageScorerFactory : IRepositoryScoreCalculatorFactory +{ + private readonly StatisticsService _service; + + public UsageScorerFactory(StatisticsService monitor) + { + _service = monitor ?? throw new ArgumentNullException(nameof(monitor)); + } + + public IRepositoryScoreCalculator Create(UsageScorerConfigurationV1 config) + { + return new UsageScoreCalculator(_service); + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj new file mode 100644 index 00000000..b9be798d --- /dev/null +++ b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + + + + + + + + + + + + + + diff --git a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs new file mode 100644 index 00000000..5369fbd8 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs @@ -0,0 +1,37 @@ +namespace RepoM.Plugin.Statistics.RepositoryActions; + +using System; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryActions; + +internal class RecordStatisticsActionExecutorDecorator : IActionExecutor where T : IAction +{ + private readonly IActionExecutor _decoratee; + private readonly StatisticsService _service; + + public RecordStatisticsActionExecutorDecorator( + IActionExecutor decoratee, + StatisticsService service) + { + _decoratee = decoratee ?? throw new ArgumentNullException(nameof(decoratee)); + _service = service ?? throw new ArgumentNullException(nameof(service)); + } + + public void Execute(IRepository repository, T action) + { + Record(repository); + _decoratee.Execute(repository, action); + } + + private void Record(IRepository repository) + { + try + { + _service.Record(repository); + } + catch (Exception) + { + // swallow + } + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsModule.cs b/src/RepoM.Plugin.Statistics/StatisticsModule.cs new file mode 100644 index 00000000..01492555 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/StatisticsModule.cs @@ -0,0 +1,28 @@ +namespace RepoM.Plugin.Statistics; + +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using RepoM.Core.Plugin; + +[UsedImplicitly] +internal class StatisticsModule : IModule +{ + private readonly StatisticsService _service; + + public StatisticsModule(StatisticsService service) + { + _service = service ?? throw new ArgumentNullException(nameof(service)); + } + + public Task StartAsync() + { + return Task.CompletedTask; + // return _service.InitializeAsync(); + } + + public Task StopAsync() + { + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs new file mode 100644 index 00000000..930838ad --- /dev/null +++ b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs @@ -0,0 +1,35 @@ +namespace RepoM.Plugin.Statistics; + +using JetBrains.Annotations; +using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; +using RepoM.Api.Ordering.Az; +using RepoM.Api.RepositoryActions.Decorators; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Plugin.Statistics.Ordering; +using SimpleInjector; +using SimpleInjector.Packaging; + +[UsedImplicitly] +public class StatisticsPackage : IPackage +{ + public void RegisterServices(Container container) + { + // container.Collection.Append(Lifestyle.Singleton); + // container.Collection.Append(Lifestyle.Singleton); + + container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append, UsageScorerFactory>(Lifestyle.Singleton); + container.Register, UsageScorerFactory>(Lifestyle.Singleton); + + container.RegisterDecorator( + typeof(IActionExecutor<>), + typeof(LoggerActionExecutorDecorator<>), + Lifestyle.Singleton); + + container.Register(Lifestyle.Singleton); + container.Collection.Append(Lifestyle.Singleton); + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs new file mode 100644 index 00000000..9267687f --- /dev/null +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -0,0 +1,33 @@ +namespace RepoM.Plugin.Statistics; + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RepoM.Core.Plugin; + +internal class StatisticsService +{ + private ReadOnlyCollection _empty = new List(0).AsReadOnly(); + private Dictionary> _recordings = new(); + + public void Record(IRepository repository) + { + if (!_recordings.TryGetValue(repository.SafePath, out List? list)) + { + list = new List(); + _recordings.TryAdd(repository.SafePath, list); + } + + list.Add(DateTime.Now); + } + + public IReadOnlyList GetRecordings(IRepository repository) + { + if (_recordings.TryGetValue(repository.SafePath, out List? list)) + { + return list.AsReadOnly(); + } + + return _empty; + } +} \ No newline at end of file From 0b9caceb0e3e5b9c9b8c6b819622a880240132f8 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sun, 27 Nov 2022 11:21:20 +0100 Subject: [PATCH 25/60] update --- .../RepoMVariableProvider.cs | 1 - .../Executors/DelegateActionExecutor.cs | 5 +- src/RepoM.App/App.xaml.cs | 101 ++++++++---------- src/RepoM.App/MainWindow.xaml.cs | 38 ++++--- .../RepositoryActions/ActionExecutor.cs | 22 ++++ .../RepositoryComparerCompositionFactory.cs | 39 +++++++ .../RepositoryScoreCalculatorFactory.cs | 39 +++++++ .../Ordering/UsageScorerConfigurationV1.cs | 5 + .../UsageScorerConfigurationV1Registration.cs | 2 +- .../Ordering/UsageScorerFactory.cs | 7 +- .../RepoM.Plugin.Statistics.csproj | 3 +- ...RecordStatisticsActionExecutorDecorator.cs | 4 +- .../StatisticsPackage.cs | 16 ++- .../StatisticsService.cs | 6 +- 14 files changed, 186 insertions(+), 102 deletions(-) create mode 100644 src/RepoM.App/RepositoryActions/ActionExecutor.cs create mode 100644 src/RepoM.App/RepositoryOrdering/RepositoryComparerCompositionFactory.cs create mode 100644 src/RepoM.App/RepositoryOrdering/RepositoryScoreCalculatorFactory.cs diff --git a/src/RepoM.Api/IO/VariableProviders/RepoMVariableProvider.cs b/src/RepoM.Api/IO/VariableProviders/RepoMVariableProvider.cs index b97bbd4c..78522215 100644 --- a/src/RepoM.Api/IO/VariableProviders/RepoMVariableProvider.cs +++ b/src/RepoM.Api/IO/VariableProviders/RepoMVariableProvider.cs @@ -1,4 +1,3 @@ - namespace RepoM.Api.IO.VariableProviders; using System; diff --git a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs index 3af6f804..bd76ce26 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs @@ -6,13 +6,10 @@ namespace RepoM.Api.RepositoryActions.Executors; public class DelegateActionExecutor : IActionExecutor { - private DelegateActionExecutor() + public DelegateActionExecutor() { } - public static DelegateActionExecutor Instance { get; } = new DelegateActionExecutor(); - - public void Execute(IRepository repository, DelegateAction action) { action.Action.Invoke(null, null); diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index 0b781fb7..11979bb4 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -38,48 +38,21 @@ namespace RepoM.App; using RepoM.Api.Ordering.IsPinned; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using RepoM.Core.Plugin.RepositoryOrdering; -using System.ComponentModel; using RepoM.Api.Ordering.Az; using RepoM.Api.Ordering.Composition; using RepoM.Api.Ordering.Label; using RepoM.Api.Ordering.Score; using RepoM.Api.Ordering.Sum; using Container = SimpleInjector.Container; +using RepoM.Api.RepositoryActions.Decorators; +using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Api.RepositoryActions.Executors; +using RepoM.App.RepositoryActions; +using RepoM.App.RepositoryOrdering; +using RepoM.Plugin.Statistics; +using RepoM.Plugin.Statistics.Ordering; -internal class RepositoryComparerCompositionFactory : IRepositoryComparerFactory -{ - private readonly Container _container; - - public RepositoryComparerCompositionFactory(Container container) - { - _container = container; - } - - public IRepositoryComparer Create(IRepositoriesComparerConfiguration configuration) - { - Type type = typeof(IRepositoryComparerFactory<>).MakeGenericType(configuration.GetType()); - dynamic factory = _container.GetInstance(type); - return factory.Create((dynamic)configuration); - } -} - -internal class RepositoryScoreCalculatorFactory : IRepositoryScoreCalculatorFactory -{ - private readonly Container _container; - - public RepositoryScoreCalculatorFactory(Container container) - { - _container = container; - } - public IRepositoryScoreCalculator Create(IRepositoryScorerConfiguration configuration) - { - Type type = typeof(IRepositoryScoreCalculatorFactory<>).MakeGenericType(configuration.GetType()); - dynamic factory = _container.GetInstance(type); - return factory.Create((dynamic)configuration); - } - -} /// /// Interaction logic for App.xaml @@ -124,11 +97,10 @@ protected override void OnStartup(StartupEventArgs e) logger.LogInformation("Started"); RegisterLogging(loggerFactory); RegisterServices(_container, fileSystem); - UseRepositoryMonitor(_container); - - _container.Verify(VerificationOption.VerifyAndDiagnose); + UseRepositoryMonitor(_container); + _updateTimer = new Timer(async _ => await CheckForUpdatesAsync(), null, 5000, Timeout.Infinite); // We noticed that the hotkey registration causes a high CPU utilization if the window was not shown before. @@ -309,47 +281,62 @@ private static void RegisterServices(Container container, IFileSystem fileSystem container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); - IEnumerable pluginDlls = PluginFinder.FindPluginAssemblies(Path.Combine(AppDomain.CurrentDomain.BaseDirectory), fileSystem); - IEnumerable assemblies = pluginDlls.Select(plugin => Assembly.Load(AssemblyName.GetAssemblyName(plugin.FullName))); - container.RegisterPackages(assemblies); + + - + container.RegisterSingleton(); + container.RegisterSingleton(); + Assembly[] xxx = + { + typeof(IConfigurationRegistration).Assembly, + typeof(IsPinnedScorerConfigurationV1Registration).Assembly, + typeof(StatisticsPackage).Assembly, + }; + container.Collection.Register(typeof(IConfigurationRegistration), xxx, Lifestyle.Singleton); - _container.RegisterSingleton(); - _container.RegisterSingleton(); + + container.Collection.Append, UsageScorerFactory>(Lifestyle.Singleton); + container.Register, UsageScorerFactory>(Lifestyle.Singleton); - _container.Collection.Register(typeof(IConfigurationRegistration), new[] { typeof(IConfigurationRegistration).Assembly, typeof(IsPinnedScorerConfigurationV1Registration).Assembly, }, Lifestyle.Singleton); // _container.Collection.Append(Lifestyle.Singleton); - _container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); - _container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); + container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); // _container.Collection.Append(Lifestyle.Singleton); - _container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); - _container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); // _container.Collection.Append(Lifestyle.Singleton); - _container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); - _container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); + container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); + container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); // _container.Collection.Append(Lifestyle.Singleton); - _container.Collection.Append, TagScorerFactory>(Lifestyle.Singleton); - _container.Register, TagScorerFactory>(Lifestyle.Singleton); + container.Collection.Append, TagScorerFactory>(Lifestyle.Singleton); + container.Register, TagScorerFactory>(Lifestyle.Singleton); // _container.Collection.Append(Lifestyle.Singleton); - _container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); - _container.Register, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); + container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); // _container.Collection.Append(Lifestyle.Singleton); - _container.Collection.Append, SumRepositoryComparerFactory>(Lifestyle.Singleton); - _container.Register, SumRepositoryComparerFactory>(Lifestyle.Singleton); - + container.Collection.Append, SumRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, SumRepositoryComparerFactory>(Lifestyle.Singleton); + container.RegisterSingleton(); + container.Register(typeof(IActionExecutor<>), new [] { typeof(BrowseActionExecutor).Assembly, }, Lifestyle.Singleton); + container.RegisterDecorator( + typeof(IActionExecutor<>), + typeof(LoggerActionExecutorDecorator<>), + Lifestyle.Singleton); + IEnumerable pluginDlls = PluginFinder.FindPluginAssemblies(Path.Combine(AppDomain.CurrentDomain.BaseDirectory), fileSystem); + IEnumerable assemblies = pluginDlls.Select(plugin => Assembly.Load(AssemblyName.GetAssemblyName(plugin.FullName))); + container.RegisterPackages(assemblies); } private static void StartModules(List modules) diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index f3821775..2372741c 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -17,10 +17,9 @@ namespace RepoM.App; using RepoM.Api.Common; using RepoM.Api.Git; using RepoM.Api.IO; -using RepoM.Api.RepositoryActions.Executors; using RepoM.App.Controls; +using RepoM.App.RepositoryActions; using RepoM.App.Services; -using RepoM.Core.Plugin.RepositoryActions.Actions; using RepoM.Core.Plugin.RepositoryOrdering; using SourceChord.FluentWPF; @@ -38,6 +37,7 @@ public partial class MainWindow private bool _refreshDelayed; private DateTime _timeOfLastRefresh = DateTime.MinValue; private readonly IFileSystem _fileSystem; + private readonly ActionExecutor _executor; private readonly IAppDataPathProvider _appDataPathProvider; public MainWindow( @@ -52,7 +52,8 @@ public MainWindow( IRepositorySearch repositorySearch, IFileSystem fileSystem, ICompareSettingsService compareSettingsService, - IRepositoryComparerFactory repositoryComparerFactory) + IRepositoryComparerFactory repositoryComparerFactory, + ActionExecutor executor) { _translationService = translationService; InitializeComponent(); @@ -74,6 +75,7 @@ public MainWindow( _appDataPathProvider = appDataPathProvider ?? throw new ArgumentNullException(nameof(appDataPathProvider)); _repositorySearch = repositorySearch ?? throw new ArgumentNullException(nameof(repositorySearch)); _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); + _executor = executor ?? throw new ArgumentNullException(nameof(executor)); lstRepositories.ItemsSource = aggregator.Repositories; @@ -81,8 +83,8 @@ public MainWindow( ((ICollectionView)view).CollectionChanged += View_CollectionChanged; view.Filter = FilterRepositories; view.CustomSort = new RepositoryComparerAdapter(repositoryComparerFactory.Create(compareSettingsService.Configuration)); - - + // view.Refresh(); // todo refresh on change of value in on of the characteristics sorting is based on. + AssemblyName? appName = Assembly.GetEntryAssembly()?.GetName(); txtHelpCaption.Text = appName?.Name + " " + appName?.Version?.ToString(2); txtHelp.Text = GetHelp(statusCharacterMap); @@ -270,9 +272,9 @@ private void InvokeActionOnCurrentRepository() action = _repositoryActionProvider.GetPrimaryAction(selectedView.Repository); } - if (action?.Action is DelegateAction da) + if (action != null) { - DelegateActionExecutor.Instance.Execute(action.Repository, da); + _executor.Execute(action.Repository, action.Action); } } @@ -389,7 +391,7 @@ private void ShowUpdateIfAvailable() parent.ColumnDefinitions[Grid.GetColumn(UpdateButton)].Width = App.AvailableUpdate == null ? new GridLength(0) : GridLength.Auto; } - private static Control? /*MenuItem*/ CreateMenuItem(object sender, RepositoryActionBase action, IEnumerable? affectedViews = null) + private Control? /*MenuItem*/ CreateMenuItem(object sender, RepositoryActionBase action, IEnumerable? affectedViews = null) { if (action is RepositorySeparatorAction) { @@ -412,22 +414,18 @@ private void ShowUpdateIfAvailable() var coords = new float[] { 0, 0, }; // run actions in the UI async to not block it - if (repositoryAction.Action is DelegateAction da) + if (repositoryAction.ExecutionCausesSynchronizing) { - if (repositoryAction.ExecutionCausesSynchronizing) - { - Task.Run(() => SetViewsSynchronizing(affectedViews, true)) - .ContinueWith(t => DelegateActionExecutor.Instance.Execute(repositoryAction.Repository, da)) //repositoryAction.Action(null, coords)) - .ContinueWith(t => SetViewsSynchronizing(affectedViews, false)); - } - else - { - Task.Run(() => DelegateActionExecutor.Instance.Execute(repositoryAction.Repository, da)); - } + Task.Run(() => SetViewsSynchronizing(affectedViews, true)) + .ContinueWith(t => + _executor.Execute(action.Repository, action.Action)) //repositoryAction.Action(null, coords)) + // .ContinueWith(t => DelegateActionExecutor.Instance.Execute(repositoryAction.Repository, da)) //repositoryAction.Action(null, coords)) + .ContinueWith(t => SetViewsSynchronizing(affectedViews, false)); } else { - throw new NotImplementedException(); + Task.Run(() => + _executor.Execute(action.Repository, action.Action)); } }; diff --git a/src/RepoM.App/RepositoryActions/ActionExecutor.cs b/src/RepoM.App/RepositoryActions/ActionExecutor.cs new file mode 100644 index 00000000..4d7f7c36 --- /dev/null +++ b/src/RepoM.App/RepositoryActions/ActionExecutor.cs @@ -0,0 +1,22 @@ +namespace RepoM.App.RepositoryActions; + +using System; +using RepoM.Core.Plugin; +using RepoM.Core.Plugin.RepositoryActions; +using SimpleInjector; + +public sealed class ActionExecutor +{ + private readonly Container _container; + + public ActionExecutor(Container container) + { + _container = container ?? throw new ArgumentNullException(nameof(container)); + } + + public void Execute(IRepository repository, IAction action) + { + dynamic executor = _container.GetInstance(typeof(IActionExecutor<>).MakeGenericType(action.GetType())); + executor.Execute((dynamic)repository, (dynamic)action); + } +} \ No newline at end of file diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryComparerCompositionFactory.cs b/src/RepoM.App/RepositoryOrdering/RepositoryComparerCompositionFactory.cs new file mode 100644 index 00000000..067c624c --- /dev/null +++ b/src/RepoM.App/RepositoryOrdering/RepositoryComparerCompositionFactory.cs @@ -0,0 +1,39 @@ +namespace RepoM.App.RepositoryOrdering; + +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.RepositoryOrdering; +using System; +using Microsoft.Extensions.Logging; +using SimpleInjector; + +internal class RepositoryComparerCompositionFactory : IRepositoryComparerFactory +{ + private readonly Container _container; + private readonly ILogger _logger; + + public RepositoryComparerCompositionFactory(Container container, ILogger logger) + { + _container = container ?? throw new ArgumentNullException(nameof(container)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public IRepositoryComparer Create(IRepositoriesComparerConfiguration configuration) + { + try + { + return CreateInner(configuration); + } + catch (Exception e) + { + _logger.LogCritical(e, "Could not create a IRepositoryComparer for configuration type '{configuration}'", configuration); + throw; + } + } + + private IRepositoryComparer CreateInner(IRepositoriesComparerConfiguration configuration) + { + Type type = typeof(IRepositoryComparerFactory<>).MakeGenericType(configuration.GetType()); + dynamic factory = _container.GetInstance(type); + return factory.Create((dynamic)configuration); + } +} \ No newline at end of file diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryScoreCalculatorFactory.cs b/src/RepoM.App/RepositoryOrdering/RepositoryScoreCalculatorFactory.cs new file mode 100644 index 00000000..5b5e8a89 --- /dev/null +++ b/src/RepoM.App/RepositoryOrdering/RepositoryScoreCalculatorFactory.cs @@ -0,0 +1,39 @@ +namespace RepoM.App.RepositoryOrdering; + +using System; +using Microsoft.Extensions.Logging; +using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using SimpleInjector; + +internal class RepositoryScoreCalculatorFactory : IRepositoryScoreCalculatorFactory +{ + private readonly Container _container; + private readonly ILogger _logger; + + public RepositoryScoreCalculatorFactory(Container container, ILogger logger) + { + _container = container ?? throw new ArgumentNullException(nameof(container)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public IRepositoryScoreCalculator Create(IRepositoryScorerConfiguration configuration) + { + try + { + return CreateInner(configuration); + } + catch (Exception e) + { + _logger.LogCritical(e, "Could not create a IRepositoryComparer for configuration type '{configuration}'", configuration); + throw; + } + } + + private IRepositoryScoreCalculator CreateInner(IRepositoryScorerConfiguration configuration) + { + Type type = typeof(IRepositoryScoreCalculatorFactory<>).MakeGenericType(configuration.GetType()); + dynamic factory = _container.GetInstance(type); + return factory.Create((dynamic)configuration); + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs index 5e7acc77..66133ecd 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs @@ -4,4 +4,9 @@ namespace RepoM.Plugin.Statistics.Ordering; public class UsageScorerConfigurationV1 : IRepositoryScorerConfiguration { + public UsageScorerConfigurationV1() + { + } + + public int Weight { get; set; } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs index d0c5a517..44d35178 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1Registration.cs @@ -9,5 +9,5 @@ public class UsageScorerConfigurationV1Registration : IConfigurationRegistration { public Type ConfigurationType { get; } = typeof(UsageScorerConfigurationV1); - public string Tag { get; } = "usage@1"; + public string Tag => "usage-scorer@1"; } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs index 4b220be3..81a191fc 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs @@ -1,16 +1,15 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; -using RepoM.Api.Git; using RepoM.Core.Plugin.RepositoryOrdering; -internal class UsageScorerFactory : IRepositoryScoreCalculatorFactory +public class UsageScorerFactory : IRepositoryScoreCalculatorFactory { private readonly StatisticsService _service; - public UsageScorerFactory(StatisticsService monitor) + public UsageScorerFactory(StatisticsService service) { - _service = monitor ?? throw new ArgumentNullException(nameof(monitor)); + _service = service ?? throw new ArgumentNullException(nameof(service)); } public IRepositoryScoreCalculator Create(UsageScorerConfigurationV1 config) diff --git a/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj index b9be798d..474a0eed 100644 --- a/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj +++ b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj @@ -11,8 +11,7 @@ - - + diff --git a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs index 5369fbd8..8d44777a 100644 --- a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs +++ b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs @@ -1,10 +1,12 @@ namespace RepoM.Plugin.Statistics.RepositoryActions; using System; +using JetBrains.Annotations; using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions; -internal class RecordStatisticsActionExecutorDecorator : IActionExecutor where T : IAction +[UsedImplicitly] +public class RecordStatisticsActionExecutorDecorator : IActionExecutor where T : IAction { private readonly IActionExecutor _decoratee; private readonly StatisticsService _service; diff --git a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs index 930838ad..4e6f217f 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs @@ -1,14 +1,12 @@ namespace RepoM.Plugin.Statistics; using JetBrains.Annotations; -using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; -using RepoM.Api.Ordering.Az; -using RepoM.Api.RepositoryActions.Decorators; using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using RepoM.Plugin.Statistics.Ordering; +using RepoM.Plugin.Statistics.RepositoryActions; using SimpleInjector; using SimpleInjector.Packaging; @@ -17,16 +15,16 @@ public class StatisticsPackage : IPackage { public void RegisterServices(Container container) { - // container.Collection.Append(Lifestyle.Singleton); - // container.Collection.Append(Lifestyle.Singleton); + // container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, UsageScorerFactory>(Lifestyle.Singleton); - container.Register, UsageScorerFactory>(Lifestyle.Singleton); + // container.Collection.Append, IRepositoryScoreCalculatorFactory>(Lifestyle.Singleton); + + // container.Collection.Append, UsageScorerFactory>(Lifestyle.Singleton); + // container.Register, UsageScorerFactory>(Lifestyle.Singleton); container.RegisterDecorator( typeof(IActionExecutor<>), - typeof(LoggerActionExecutorDecorator<>), + typeof(RecordStatisticsActionExecutorDecorator<>), Lifestyle.Singleton); container.Register(Lifestyle.Singleton); diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs index 9267687f..015f8f3a 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsService.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -5,10 +5,10 @@ namespace RepoM.Plugin.Statistics; using System.Collections.ObjectModel; using RepoM.Core.Plugin; -internal class StatisticsService +public class StatisticsService { - private ReadOnlyCollection _empty = new List(0).AsReadOnly(); - private Dictionary> _recordings = new(); + private readonly ReadOnlyCollection _empty = new List(0).AsReadOnly(); + private readonly Dictionary> _recordings = new(); public void Record(IRepository repository) { From 708f270aa1e1118b71705e7b6f39267ff5c19467 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sun, 27 Nov 2022 12:26:05 +0100 Subject: [PATCH 26/60] Update --- src/RepoM.App/App.xaml.cs | 41 +++---------------- .../Ordering/UsageScorerConfigurationV1.cs | 2 +- .../Ordering/UsageScorerFactory.cs | 2 +- ...RecordStatisticsActionExecutorDecorator.cs | 2 +- .../StatisticsPackage.cs | 18 +++----- 5 files changed, 15 insertions(+), 50 deletions(-) diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index 11979bb4..b9ac0e52 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -281,51 +281,22 @@ private static void RegisterServices(Container container, IFileSystem fileSystem container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); - - - container.RegisterSingleton(); container.RegisterSingleton(); - Assembly[] xxx = - { - typeof(IConfigurationRegistration).Assembly, - typeof(IsPinnedScorerConfigurationV1Registration).Assembly, - typeof(StatisticsPackage).Assembly, - }; - container.Collection.Register(typeof(IConfigurationRegistration), xxx, Lifestyle.Singleton); - - - container.Collection.Append, UsageScorerFactory>(Lifestyle.Singleton); - container.Register, UsageScorerFactory>(Lifestyle.Singleton); - - - // _container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); - container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); - - // _container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); - container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); + container.Collection.Register( + typeof(IConfigurationRegistration), + new[] { typeof(IConfigurationRegistration).Assembly, typeof(IsPinnedScorerConfigurationV1Registration).Assembly, }, + Lifestyle.Singleton); - // _container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); - - // _container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, TagScorerFactory>(Lifestyle.Singleton); container.Register, TagScorerFactory>(Lifestyle.Singleton); - - // _container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); + container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); container.Register, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); - - // _container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, SumRepositoryComparerFactory>(Lifestyle.Singleton); container.Register, SumRepositoryComparerFactory>(Lifestyle.Singleton); - container.RegisterSingleton(); container.Register(typeof(IActionExecutor<>), new [] { typeof(BrowseActionExecutor).Assembly, }, Lifestyle.Singleton); container.RegisterDecorator( diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs index 66133ecd..6511747a 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs @@ -2,7 +2,7 @@ namespace RepoM.Plugin.Statistics.Ordering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -public class UsageScorerConfigurationV1 : IRepositoryScorerConfiguration +public sealed class UsageScorerConfigurationV1 : IRepositoryScorerConfiguration { public UsageScorerConfigurationV1() { diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs index 81a191fc..5fe60a6d 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs @@ -3,7 +3,7 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; using RepoM.Core.Plugin.RepositoryOrdering; -public class UsageScorerFactory : IRepositoryScoreCalculatorFactory +public sealed class UsageScorerFactory : IRepositoryScoreCalculatorFactory { private readonly StatisticsService _service; diff --git a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs index 8d44777a..92fd51c7 100644 --- a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs +++ b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs @@ -6,7 +6,7 @@ namespace RepoM.Plugin.Statistics.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions; [UsedImplicitly] -public class RecordStatisticsActionExecutorDecorator : IActionExecutor where T : IAction +public sealed class RecordStatisticsActionExecutorDecorator : IActionExecutor where T : IAction { private readonly IActionExecutor _decoratee; private readonly StatisticsService _service; diff --git a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs index 4e6f217f..52aaf3d6 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs @@ -15,19 +15,13 @@ public class StatisticsPackage : IPackage { public void RegisterServices(Container container) { - // container.Collection.Append(Lifestyle.Singleton); - - // container.Collection.Append, IRepositoryScoreCalculatorFactory>(Lifestyle.Singleton); - - // container.Collection.Append, UsageScorerFactory>(Lifestyle.Singleton); - // container.Register, UsageScorerFactory>(Lifestyle.Singleton); - - container.RegisterDecorator( - typeof(IActionExecutor<>), - typeof(RecordStatisticsActionExecutorDecorator<>), - Lifestyle.Singleton); + // Plugin registrations + container.Collection.Append(Lifestyle.Singleton); + container.Register, UsageScorerFactory>(Lifestyle.Singleton); + container.RegisterDecorator(typeof(IActionExecutor<>), typeof(RecordStatisticsActionExecutorDecorator<>), Lifestyle.Singleton); + container.Collection.Append(Lifestyle.Singleton); + // Internal registrations container.Register(Lifestyle.Singleton); - container.Collection.Append(Lifestyle.Singleton); } } \ No newline at end of file From c9c17b38ea2afcbc64b0cad50d150f83ceb3d5e6 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 28 Nov 2022 14:21:59 +0100 Subject: [PATCH 27/60] . --- RepoM.sln.DotSettings | 1 + src/RepoM.Api/Git/DefaultRepositoryReader.cs | 4 +- src/RepoM.Api/Git/Repository.cs | 2 +- src/RepoM.Api/Git/RepositoryAction.cs | 2 +- .../ExpressionEvaluator/RepositoryContext.cs | 26 ---------- .../RepositoryExpressionEvaluator.cs | 1 + .../IO/GravellGitRepositoryFinderFactory.cs | 2 +- src/RepoM.Api/IO/IPathFinder.cs | 1 + .../ActionAssociateFileV1Mapper.cs | 2 +- .../ActionBrowseRepositoryV1Mapper.cs | 2 +- .../RepositorySpecificConfiguration.cs | 4 +- ...stomEnvironmentVariableVariableProvider.cs | 7 ++- .../RepositoryVariableProvider.cs | 5 +- .../VariableProviderAdapter.cs | 52 +++++++++++++++++++ .../IO/Variables/EnvironmentVariableStore.cs | 3 +- ...abetComparerConfigurationV1Registration.cs | 2 +- src/RepoM.Api/Ordering/Az/AzComparer.cs | 2 +- .../Composition/CompositionComparer.cs | 2 +- ...tionComparerConfigurationV1Registration.cs | 2 +- .../IsPinned/IsPinnedScoreCalculator.cs | 2 +- ...PinnedScorerConfigurationV1Registration.cs | 2 +- .../Ordering/Label/TagScoreCalculator.cs | 2 +- .../TagScorerConfigurationV1Registration.cs | 2 +- src/RepoM.Api/Ordering/Score/ScoreComparer.cs | 2 +- ...coreComparerConfigurationV1Registration.cs | 2 +- .../SumComparerConfigurationV1Registration.cs | 2 +- .../Ordering/Sum/SumCompositionComparer.cs | 2 +- .../LoggerActionExecutorDecorator.cs | 2 +- .../Executors/BrowseActionExecutor.cs | 2 +- .../Executors/DelegateActionExecutor.cs | 6 +-- .../Executors/NullActionExecutor.cs | 2 +- src/RepoM.App/App.xaml.cs | 7 +-- src/RepoM.App/RepoM.App.csproj | 4 -- .../RepositoryActions/ActionExecutor.cs | 2 +- .../{ => Repository}/IRepository.cs | 6 ++- .../Repository}/Remote.cs | 6 +-- .../Repository/RepositoryContext.cs | 25 +++++++++ .../Actions/DelegateAction.cs | 4 +- .../RepositoryActions/IActionExecutor.cs | 2 + .../RepositoryOrdering/IRepositoryComparer.cs | 1 + .../IRepositoryScoreCalculator.cs | 2 + .../VariableProviders/IVariableProvider.cs | 22 ++++++++ .../VariableProviders/IVariableProvider{T}.cs | 17 ++++++ .../EverythingGitRepositoryFinderFactory.cs | 2 +- .../Ordering/UsageScoreCalculator.cs | 2 +- ...RecordStatisticsActionExecutorDecorator.cs | 2 +- .../StatisticsPackage.cs | 21 +++++++- .../StatisticsService.cs | 2 +- .../UsageVariableProvider.cs | 33 ++++++++++++ tests/Yaml.Poc.Tests/YamlTests.cs | 5 +- 50 files changed, 227 insertions(+), 88 deletions(-) delete mode 100644 src/RepoM.Api/IO/ExpressionEvaluator/RepositoryContext.cs create mode 100644 src/RepoM.Api/IO/VariableProviders/VariableProviderAdapter.cs rename src/RepoM.Core.Plugin/{ => Repository}/IRepository.cs (71%) rename src/{RepoM.Api/Git => RepoM.Core.Plugin/Repository}/Remote.cs (94%) create mode 100644 src/RepoM.Core.Plugin/Repository/RepositoryContext.cs create mode 100644 src/RepoM.Core.Plugin/VariableProviders/IVariableProvider.cs create mode 100644 src/RepoM.Core.Plugin/VariableProviders/IVariableProvider{T}.cs create mode 100644 src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs diff --git a/RepoM.sln.DotSettings b/RepoM.sln.DotSettings index 7f128dd7..d49b350a 100644 --- a/RepoM.sln.DotSettings +++ b/RepoM.sln.DotSettings @@ -1,5 +1,6 @@  True + True True True True diff --git a/src/RepoM.Api/Git/DefaultRepositoryReader.cs b/src/RepoM.Api/Git/DefaultRepositoryReader.cs index deba0a83..e42949a5 100644 --- a/src/RepoM.Api/Git/DefaultRepositoryReader.cs +++ b/src/RepoM.Api/Git/DefaultRepositoryReader.cs @@ -113,9 +113,9 @@ public DefaultRepositoryReader(IRepositoryTagsFactory resolver, ILogger logger) RemoteCollection? remoteCollection = repo.Network?.Remotes; if (remoteCollection != null) { - foreach (LibGit2Sharp.Remote r in remoteCollection.Where(r => !string.IsNullOrWhiteSpace(r.Name) && !string.IsNullOrWhiteSpace(r.Url))) + foreach (Remote r in remoteCollection.Where(r => !string.IsNullOrWhiteSpace(r.Name) && !string.IsNullOrWhiteSpace(r.Url))) { - repository.Remotes.Add(new Remote(r.Name.Trim(), r.Url.Trim())); + repository.Remotes.Add(new Core.Plugin.Repository.Remote(r.Name.Trim(), r.Url.Trim())); } } diff --git a/src/RepoM.Api/Git/Repository.cs b/src/RepoM.Api/Git/Repository.cs index 398ac243..fc3352b2 100644 --- a/src/RepoM.Api/Git/Repository.cs +++ b/src/RepoM.Api/Git/Repository.cs @@ -3,7 +3,7 @@ namespace RepoM.Api.Git; using System; using System.Collections.Generic; using System.Diagnostics; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; [DebuggerDisplay("{Name} @{Path}")] public class Repository : IRepository diff --git a/src/RepoM.Api/Git/RepositoryAction.cs b/src/RepoM.Api/Git/RepositoryAction.cs index 156bd15a..16c47e37 100644 --- a/src/RepoM.Api/Git/RepositoryAction.cs +++ b/src/RepoM.Api/Git/RepositoryAction.cs @@ -2,7 +2,7 @@ namespace RepoM.Api.Git; using System; using System.Collections.Generic; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; diff --git a/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryContext.cs b/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryContext.cs deleted file mode 100644 index 2ac996bb..00000000 --- a/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryContext.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace RepoM.Api.IO.ExpressionEvaluator; - -using System; -using System.Collections.Generic; -using System.Linq; -using RepoM.Api.Git; - -public sealed class RepositoryContext -{ - public RepositoryContext() - { - Repositories = Array.Empty(); - } - - public RepositoryContext(params Repository[] repositories) - { - Repositories = repositories.ToArray(); - } - - public RepositoryContext(IEnumerable repositories) - { - Repositories = repositories.ToArray(); - } - - public Repository[] Repositories { get; } -} \ No newline at end of file diff --git a/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs b/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs index 1734c71a..959b1770 100644 --- a/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs +++ b/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs @@ -7,6 +7,7 @@ namespace RepoM.Api.IO.ExpressionEvaluator; using ExpressionStringEvaluator.Parser; using ExpressionStringEvaluator.VariableProviders; using RepoM.Api.Git; +using RepoM.Core.Plugin.Repository; public class RepositoryExpressionEvaluator { diff --git a/src/RepoM.Api/IO/GravellGitRepositoryFinderFactory.cs b/src/RepoM.Api/IO/GravellGitRepositoryFinderFactory.cs index 8b22d8d1..22b7846d 100644 --- a/src/RepoM.Api/IO/GravellGitRepositoryFinderFactory.cs +++ b/src/RepoM.Api/IO/GravellGitRepositoryFinderFactory.cs @@ -18,7 +18,7 @@ public GravellGitRepositoryFinderFactory(IPathSkipper pathSkipper, IFileSystem f public string Name => FACTORY_NAME; - public bool IsActive { get; } = true; + public bool IsActive => true; public IGitRepositoryFinder Create() { diff --git a/src/RepoM.Api/IO/IPathFinder.cs b/src/RepoM.Api/IO/IPathFinder.cs index 44e8d5c9..6df0a3fc 100644 --- a/src/RepoM.Api/IO/IPathFinder.cs +++ b/src/RepoM.Api/IO/IPathFinder.cs @@ -2,6 +2,7 @@ namespace RepoM.Api.IO; using System; +// todo, check original code where this was used?! public interface IPathFinder { bool CanHandle(string processName); diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs index 6f2bed70..b0cea23f 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionAssociateFileV1Mapper.cs @@ -8,7 +8,7 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions.Actions; using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs index a75db609..5e8e62e5 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionBrowseRepositoryV1Mapper.cs @@ -7,7 +7,7 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.Git; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions.Actions; public class ActionBrowseRepositoryV1Mapper : IActionToRepositoryActionMapper diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs index 33c597d9..ef3c7431 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs @@ -7,7 +7,6 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using System.Linq; using System.Text; using DotNetEnv; -using LibGit2Sharp; using Microsoft.Extensions.Logging; using RepoM.Api.Common; using RepoM.Api.Git; @@ -17,9 +16,8 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Deserialization; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Exceptions; using RepoM.Api.IO.Variables; -using RepoM.Core.Plugin; using RepoM.Core.Plugin.RepositoryActions.Actions; -using IRepository = RepoM.Core.Plugin.IRepository; +using IRepository = RepoM.Core.Plugin.Repository.IRepository; using Repository = RepoM.Api.Git.Repository; using RepositoryAction = RepoM.Api.Git.RepositoryAction; diff --git a/src/RepoM.Api/IO/VariableProviders/CustomEnvironmentVariableVariableProvider.cs b/src/RepoM.Api/IO/VariableProviders/CustomEnvironmentVariableVariableProvider.cs index c6090db7..6522f332 100644 --- a/src/RepoM.Api/IO/VariableProviders/CustomEnvironmentVariableVariableProvider.cs +++ b/src/RepoM.Api/IO/VariableProviders/CustomEnvironmentVariableVariableProvider.cs @@ -5,9 +5,8 @@ namespace RepoM.Api.IO.VariableProviders; using System.Linq; using ExpressionStringEvaluator.VariableProviders; using JetBrains.Annotations; -using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.Variables; -using Repository = Git.Repository; +using RepoM.Core.Plugin.Repository; [UsedImplicitly] public class CustomEnvironmentVariableVariableProvider : IVariableProvider @@ -38,7 +37,7 @@ public bool CanProvide(string key) var prefixLength = PREFIX.Length; var envKey = key.Substring(prefixLength, key.Length - prefixLength); - Repository? singleContext = context.Repositories.SingleOrDefault(); + IRepository? singleContext = context.Repositories.SingleOrDefault(); if (singleContext == null) { @@ -63,7 +62,7 @@ public bool CanProvide(string key) return result; } - private static Dictionary GetRepoEnvironmentVariables(Repository repository) + private static Dictionary GetRepoEnvironmentVariables(IRepository repository) { return EnvironmentVariableStore.Get(repository); } diff --git a/src/RepoM.Api/IO/VariableProviders/RepositoryVariableProvider.cs b/src/RepoM.Api/IO/VariableProviders/RepositoryVariableProvider.cs index 96c6a295..579a0cf8 100644 --- a/src/RepoM.Api/IO/VariableProviders/RepositoryVariableProvider.cs +++ b/src/RepoM.Api/IO/VariableProviders/RepositoryVariableProvider.cs @@ -3,8 +3,7 @@ namespace RepoM.Api.IO.VariableProviders; using System; using System.Linq; using ExpressionStringEvaluator.VariableProviders; -using RepoM.Api.Git; -using RepoM.Api.IO.ExpressionEvaluator; +using RepoM.Core.Plugin.Repository; public class RepositoryVariableProvider : IVariableProvider { @@ -25,7 +24,7 @@ public bool CanProvide(string key) private static string ProvideString(RepositoryContext context, string key, string? arg) { - Repository? repository = context.Repositories.SingleOrDefault(); + IRepository? repository = context.Repositories.SingleOrDefault(); if (repository == null) { return string.Empty; diff --git a/src/RepoM.Api/IO/VariableProviders/VariableProviderAdapter.cs b/src/RepoM.Api/IO/VariableProviders/VariableProviderAdapter.cs new file mode 100644 index 00000000..d5c15965 --- /dev/null +++ b/src/RepoM.Api/IO/VariableProviders/VariableProviderAdapter.cs @@ -0,0 +1,52 @@ +namespace RepoM.Api.IO.VariableProviders; + +using System; +using System.Collections.Generic; +using System.Linq; +using Core.Plugin.Repository; +using JetBrains.Annotations; +using PluginVariableProvider = Core.Plugin.VariableProviders.IVariableProvider; +using PluginRepositoryContextVariableProvider = Core.Plugin.VariableProviders.IVariableProvider; + +[UsedImplicitly] +public class VariableProviderAdapter : ExpressionStringEvaluator.VariableProviders.IVariableProvider +{ + private readonly PluginVariableProvider[] _variableProviderImplementation; + + public VariableProviderAdapter(IEnumerable variableProviders) + { + _variableProviderImplementation = variableProviders.ToArray(); + } + + public bool CanProvide(string key) + { + return GetProvider(key) != null; + } + + public object? Provide(string key, string? arg) + { + throw new NotImplementedException(); + } + + public object? Provide(RepositoryContext context, string key, string? arg) + { + PluginVariableProvider? instance = GetProvider(key); + + if (instance == null) + { + throw new NullReferenceException(); + } + + if (instance is PluginRepositoryContextVariableProvider typedInstance) + { + return typedInstance.Provide(context, key, arg); + } + + return instance.Provide(key, arg); + } + + private PluginVariableProvider? GetProvider(string key) + { + return _variableProviderImplementation.FirstOrDefault(x => x.CanProvide(key)); + } +} \ No newline at end of file diff --git a/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs b/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs index 45ae9b6b..79e7c934 100644 --- a/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs +++ b/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs @@ -4,6 +4,7 @@ namespace RepoM.Api.IO.Variables; using System.Collections.Generic; using System.Threading; using RepoM.Api.Git; +using RepoM.Core.Plugin.Repository; public static class EnvironmentVariableStore { @@ -20,7 +21,7 @@ public static IDisposable Set(Dictionary? envVars) return new ExecuteOnDisposed(() => _envVars.Value = new Dictionary()); } - public static Dictionary Get(Repository _) + public static Dictionary Get(IRepository _) { return _envVars.Value ?? new Dictionary(0); } diff --git a/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1Registration.cs index f24d3882..f7a388b3 100644 --- a/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Az/AlphabetComparerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class AlphabetComparerConfigurationV1Registration : IConfigurationRegistr { public Type ConfigurationType { get; } = typeof(AlphabetComparerConfigurationV1); - public string Tag { get; } = "az-comparer@1"; + public string Tag => "az-comparer@1"; } \ No newline at end of file diff --git a/src/RepoM.Api/Ordering/Az/AzComparer.cs b/src/RepoM.Api/Ordering/Az/AzComparer.cs index 749c72ae..007bb648 100644 --- a/src/RepoM.Api/Ordering/Az/AzComparer.cs +++ b/src/RepoM.Api/Ordering/Az/AzComparer.cs @@ -1,7 +1,7 @@ namespace RepoM.Api.Ordering.Az; using System; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; public class AzComparer : IRepositoryComparer diff --git a/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs b/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs index 5a0e0140..3c15f40d 100644 --- a/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs +++ b/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs @@ -2,7 +2,7 @@ namespace RepoM.Api.Ordering.Composition; using System.Collections.Generic; using System.Linq; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; public class CompositionComparer : IRepositoryComparer diff --git a/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1Registration.cs index 959317ea..933733f7 100644 --- a/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Composition/CompositionComparerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class CompositionComparerConfigurationV1Registration : IConfigurationRegi { public Type ConfigurationType { get; } = typeof(CompositionComparerConfigurationV1); - public string Tag { get; } = "composition@1"; + public string Tag => "composition@1"; } \ No newline at end of file diff --git a/src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs index a45385ac..bacc4818 100644 --- a/src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs +++ b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScoreCalculator.cs @@ -2,7 +2,7 @@ namespace RepoM.Api.Ordering.IsPinned; using System; using RepoM.Api.Git; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; public class IsPinnedScoreCalculator : IRepositoryScoreCalculator diff --git a/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1Registration.cs index 52187348..3abfa329 100644 --- a/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/IsPinned/IsPinnedScorerConfigurationV1Registration.cs @@ -9,5 +9,5 @@ public class IsPinnedScorerConfigurationV1Registration : IConfigurationRegistrat { public Type ConfigurationType { get; } = typeof(IsPinnedScorerConfigurationV1); - public string Tag { get; } = "is-pinned-scorer@1"; + public string Tag => "is-pinned-scorer@1"; } \ No newline at end of file diff --git a/src/RepoM.Api/Ordering/Label/TagScoreCalculator.cs b/src/RepoM.Api/Ordering/Label/TagScoreCalculator.cs index b886704c..2c6627c1 100644 --- a/src/RepoM.Api/Ordering/Label/TagScoreCalculator.cs +++ b/src/RepoM.Api/Ordering/Label/TagScoreCalculator.cs @@ -1,7 +1,7 @@ namespace RepoM.Api.Ordering.Label; using System.Linq; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; public class TagScoreCalculator : IRepositoryScoreCalculator diff --git a/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1Registration.cs index 14826361..c9a2f9e9 100644 --- a/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Label/TagScorerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class TagScorerConfigurationV1Registration : IConfigurationRegistration { public Type ConfigurationType { get; } = typeof(TagScorerConfigurationV1); - public string Tag { get; } = "tag-scorer@1"; + public string Tag => "tag-scorer@1"; } \ No newline at end of file diff --git a/src/RepoM.Api/Ordering/Score/ScoreComparer.cs b/src/RepoM.Api/Ordering/Score/ScoreComparer.cs index 251b6460..db1adf72 100644 --- a/src/RepoM.Api/Ordering/Score/ScoreComparer.cs +++ b/src/RepoM.Api/Ordering/Score/ScoreComparer.cs @@ -1,7 +1,7 @@ namespace RepoM.Api.Ordering.Score; using System; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; public class ScoreComparer : IRepositoryComparer diff --git a/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1Registration.cs index 3decb149..f4562577 100644 --- a/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Score/ScoreComparerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class ScoreComparerConfigurationV1Registration : IConfigurationRegistrati { public Type ConfigurationType { get; } = typeof(ScoreComparerConfigurationV1); - public string Tag { get; } = "score-comparer@1"; + public string Tag => "score-comparer@1"; } diff --git a/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1Registration.cs b/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1Registration.cs index 8c31f259..ef962f84 100644 --- a/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1Registration.cs +++ b/src/RepoM.Api/Ordering/Sum/SumComparerConfigurationV1Registration.cs @@ -7,5 +7,5 @@ public class SumComparerConfigurationV1Registration : IConfigurationRegistration { public Type ConfigurationType { get; } = typeof(SumComparerConfigurationV1); - public string Tag { get; } = "sum-comparer@1"; + public string Tag => "sum-comparer@1"; } \ No newline at end of file diff --git a/src/RepoM.Api/Ordering/Sum/SumCompositionComparer.cs b/src/RepoM.Api/Ordering/Sum/SumCompositionComparer.cs index 717d719d..e1eeddfe 100644 --- a/src/RepoM.Api/Ordering/Sum/SumCompositionComparer.cs +++ b/src/RepoM.Api/Ordering/Sum/SumCompositionComparer.cs @@ -2,7 +2,7 @@ namespace RepoM.Api.Ordering.Sum; using System.Collections.Generic; using System.Linq; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; public class SumCompositionComparer : IRepositoryComparer diff --git a/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs b/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs index 163aed7f..00c7efe3 100644 --- a/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs +++ b/src/RepoM.Api/RepositoryActions/Decorators/LoggerActionExecutorDecorator.cs @@ -1,6 +1,6 @@ namespace RepoM.Api.RepositoryActions.Decorators; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; public class LoggerActionExecutorDecorator : IActionExecutor where T : IAction diff --git a/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs index 6984fec4..722d7ce1 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs @@ -1,7 +1,7 @@ namespace RepoM.Api.RepositoryActions.Executors; using System; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; diff --git a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs index bd76ce26..52a66005 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs @@ -1,15 +1,11 @@ namespace RepoM.Api.RepositoryActions.Executors; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; public class DelegateActionExecutor : IActionExecutor { - public DelegateActionExecutor() - { - } - public void Execute(IRepository repository, DelegateAction action) { action.Action.Invoke(null, null); diff --git a/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs index c631e668..937eebff 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs @@ -1,6 +1,6 @@ namespace RepoM.Api.RepositoryActions.Executors; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index b9ac0e52..9173bc05 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -49,10 +49,6 @@ namespace RepoM.App; using RepoM.Api.RepositoryActions.Executors; using RepoM.App.RepositoryActions; using RepoM.App.RepositoryOrdering; -using RepoM.Plugin.Statistics; -using RepoM.Plugin.Statistics.Ordering; - - /// /// Interaction logic for App.xaml @@ -242,7 +238,7 @@ private static void RegisterServices(Container container, IFileSystem fileSystem typeof(IVariableProvider).Assembly, typeof(RepositoryExpressionEvaluator).Assembly, }; - // container.Collection.Register(typeof(IVariableProvider), repoExpressionEvaluators, Lifestyle.Singleton); + container.Collection.Append(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); @@ -252,6 +248,7 @@ private static void RegisterServices(Container container, IFileSystem fileSystem container.Collection.Append(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); + container.Collection.Append(Lifestyle.Singleton); container.Collection.Register(typeof(IMethod), repoExpressionEvaluators, Lifestyle.Singleton); container.RegisterInstance(new DateTimeVariableProviderOptions diff --git a/src/RepoM.App/RepoM.App.csproj b/src/RepoM.App/RepoM.App.csproj index ab80b466..33ed14dc 100644 --- a/src/RepoM.App/RepoM.App.csproj +++ b/src/RepoM.App/RepoM.App.csproj @@ -69,9 +69,5 @@ Settings.Designer.cs - - - - \ No newline at end of file diff --git a/src/RepoM.App/RepositoryActions/ActionExecutor.cs b/src/RepoM.App/RepositoryActions/ActionExecutor.cs index 4d7f7c36..14730655 100644 --- a/src/RepoM.App/RepositoryActions/ActionExecutor.cs +++ b/src/RepoM.App/RepositoryActions/ActionExecutor.cs @@ -1,7 +1,7 @@ namespace RepoM.App.RepositoryActions; using System; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using SimpleInjector; diff --git a/src/RepoM.Core.Plugin/IRepository.cs b/src/RepoM.Core.Plugin/Repository/IRepository.cs similarity index 71% rename from src/RepoM.Core.Plugin/IRepository.cs rename to src/RepoM.Core.Plugin/Repository/IRepository.cs index 32c16257..431d4402 100644 --- a/src/RepoM.Core.Plugin/IRepository.cs +++ b/src/RepoM.Core.Plugin/Repository/IRepository.cs @@ -1,4 +1,6 @@ -namespace RepoM.Core.Plugin; +namespace RepoM.Core.Plugin.Repository; + +using System.Collections.Generic; public interface IRepository { @@ -17,4 +19,6 @@ public interface IRepository string[] Tags { get; } string SafePath { get; } + + List Remotes { get; } } \ No newline at end of file diff --git a/src/RepoM.Api/Git/Remote.cs b/src/RepoM.Core.Plugin/Repository/Remote.cs similarity index 94% rename from src/RepoM.Api/Git/Remote.cs rename to src/RepoM.Core.Plugin/Repository/Remote.cs index c10ddaf9..191a986b 100644 --- a/src/RepoM.Api/Git/Remote.cs +++ b/src/RepoM.Core.Plugin/Repository/Remote.cs @@ -1,4 +1,4 @@ -namespace RepoM.Api.Git; +namespace RepoM.Core.Plugin.Repository; using System; using System.Diagnostics; @@ -16,7 +16,7 @@ public Remote(string key, string url) public string Key { get; } - public string Name { get; set; } + public string Name { get; } public string Url { get; } @@ -39,7 +39,7 @@ private static string CalculateName(string url) { return name; } - + try { var parts = url.Split('/', '\\'); diff --git a/src/RepoM.Core.Plugin/Repository/RepositoryContext.cs b/src/RepoM.Core.Plugin/Repository/RepositoryContext.cs new file mode 100644 index 00000000..e8a1ebfd --- /dev/null +++ b/src/RepoM.Core.Plugin/Repository/RepositoryContext.cs @@ -0,0 +1,25 @@ +namespace RepoM.Core.Plugin.Repository; + +using System; +using System.Collections.Generic; +using System.Linq; + +public sealed class RepositoryContext +{ + public RepositoryContext() + { + Repositories = Array.Empty(); + } + + public RepositoryContext(params IRepository[] repositories) + { + Repositories = repositories.ToArray(); + } + + public RepositoryContext(IEnumerable repositories) + { + Repositories = repositories.ToArray(); + } + + public IRepository[] Repositories { get; } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs b/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs index 72abe43f..0f9985ab 100644 --- a/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs +++ b/src/RepoM.Core.Plugin/RepositoryActions/Actions/DelegateAction.cs @@ -5,10 +5,10 @@ namespace RepoM.Core.Plugin.RepositoryActions.Actions; public sealed class DelegateAction : IAction { - public DelegateAction(Action action) + public DelegateAction(Action action) { Action = action ?? throw new ArgumentNullException(nameof(action)); } - public Action Action { get; } + public Action Action { get; } } \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs b/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs index f301a81f..17848262 100644 --- a/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs +++ b/src/RepoM.Core.Plugin/RepositoryActions/IActionExecutor.cs @@ -1,5 +1,7 @@ namespace RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.Repository; + public interface IActionExecutor where T : IAction { void Execute(IRepository repository, T action); diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs index 0178d0cd..05c90de3 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryComparer.cs @@ -1,6 +1,7 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; using System.Collections.Generic; +using RepoM.Core.Plugin.Repository; public interface IRepositoryComparer : IComparer { diff --git a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs index d60e06da..a3107606 100644 --- a/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs +++ b/src/RepoM.Core.Plugin/RepositoryOrdering/IRepositoryScoreCalculator.cs @@ -1,5 +1,7 @@ namespace RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.Repository; + public interface IRepositoryScoreCalculator { int Score(IRepository repository); diff --git a/src/RepoM.Core.Plugin/VariableProviders/IVariableProvider.cs b/src/RepoM.Core.Plugin/VariableProviders/IVariableProvider.cs new file mode 100644 index 00000000..9726cb02 --- /dev/null +++ b/src/RepoM.Core.Plugin/VariableProviders/IVariableProvider.cs @@ -0,0 +1,22 @@ +namespace RepoM.Core.Plugin.VariableProviders; + +/// +/// IVariableProvider. +/// +public interface IVariableProvider +{ + /// + /// CanProvide. + /// + /// key. + /// bool. + bool CanProvide(string key); + + /// + /// Provide. + /// + /// key. + /// arguments. + /// variable value. + object? Provide(string key, string? arg); +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/VariableProviders/IVariableProvider{T}.cs b/src/RepoM.Core.Plugin/VariableProviders/IVariableProvider{T}.cs new file mode 100644 index 00000000..3e522b0b --- /dev/null +++ b/src/RepoM.Core.Plugin/VariableProviders/IVariableProvider{T}.cs @@ -0,0 +1,17 @@ +namespace RepoM.Core.Plugin.VariableProviders; + +/// +/// Typed IVariableProvider. +/// +/// Context type. +public interface IVariableProvider : IVariableProvider +{ + /// + /// Provide. + /// + /// The context. + /// key. + /// arguments. + /// variable value. + object? Provide(T context, string key, string? arg); +} \ No newline at end of file diff --git a/src/RepoM.Plugin.EverythingFileSearch/EverythingGitRepositoryFinderFactory.cs b/src/RepoM.Plugin.EverythingFileSearch/EverythingGitRepositoryFinderFactory.cs index e25ac7e6..1b446c00 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/EverythingGitRepositoryFinderFactory.cs +++ b/src/RepoM.Plugin.EverythingFileSearch/EverythingGitRepositoryFinderFactory.cs @@ -17,7 +17,7 @@ public EverythingGitRepositoryFinderFactory(IPathSkipper pathSkipper) _pathSkipper = pathSkipper ?? throw new ArgumentNullException(nameof(pathSkipper)); } - public string Name { get; } = "Everything"; + public string Name => "Everything"; public bool IsActive => _isInstalled.Value; diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs index 4f866da9..c0ec962d 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs @@ -2,7 +2,7 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; using System.Collections.Generic; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; internal class UsageScoreCalculator : IRepositoryScoreCalculator diff --git a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs index 92fd51c7..835c3590 100644 --- a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs +++ b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs @@ -2,7 +2,7 @@ namespace RepoM.Plugin.Statistics.RepositoryActions; using System; using JetBrains.Annotations; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; [UsedImplicitly] diff --git a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs index 52aaf3d6..ddcb6170 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs @@ -5,8 +5,10 @@ namespace RepoM.Plugin.Statistics; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; +using RepoM.Core.Plugin.VariableProviders; using RepoM.Plugin.Statistics.Ordering; using RepoM.Plugin.Statistics.RepositoryActions; +using RepoM.Plugin.Statistics.VariableProviders; using SimpleInjector; using SimpleInjector.Packaging; @@ -15,13 +17,28 @@ public class StatisticsPackage : IPackage { public void RegisterServices(Container container) { - // Plugin registrations + RegisterPluginHooks(container); + RegisterInternals(container); + } + + private static void RegisterPluginHooks(Container container) + { + // ordering container.Collection.Append(Lifestyle.Singleton); container.Register, UsageScorerFactory>(Lifestyle.Singleton); + + // action executor container.RegisterDecorator(typeof(IActionExecutor<>), typeof(RecordStatisticsActionExecutorDecorator<>), Lifestyle.Singleton); + + // variable provider + container.Collection.Append(Lifestyle.Singleton); + + // module container.Collection.Append(Lifestyle.Singleton); + } - // Internal registrations + private static void RegisterInternals(Container container) + { container.Register(Lifestyle.Singleton); } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs index 015f8f3a..4d1709b5 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsService.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -3,7 +3,7 @@ namespace RepoM.Plugin.Statistics; using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; public class StatisticsService { diff --git a/src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs b/src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs new file mode 100644 index 00000000..6cf6f0eb --- /dev/null +++ b/src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs @@ -0,0 +1,33 @@ +namespace RepoM.Plugin.Statistics.VariableProviders; + +using System; +using System.Linq; +using JetBrains.Annotations; +using RepoM.Core.Plugin.Repository; +using RepoM.Core.Plugin.VariableProviders; + +[UsedImplicitly] +public class UsageVariableProvider : IVariableProvider +{ + private readonly StatisticsService _service; + + public UsageVariableProvider(StatisticsService service) + { + _service = service ?? throw new ArgumentNullException(nameof(service)); + } + + public bool CanProvide(string key) + { + return !string.IsNullOrWhiteSpace(key) && key.StartsWith("usage", StringComparison.CurrentCultureIgnoreCase); + } + + public object? Provide(RepositoryContext context, string key, string? arg) + { + return _service.GetRecordings(context.Repositories.First()).Count; + } + + public object? Provide(string key, string? arg) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs index 7da425a0..56f25c03 100644 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ b/tests/Yaml.Poc.Tests/YamlTests.cs @@ -7,7 +7,7 @@ namespace Yaml.Poc.Tests; using RepoM.Api.Ordering.IsPinned; using RepoM.Api.Ordering.Score; using RepoM.Api.Ordering.Sum; -using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using SimpleInjector; @@ -88,7 +88,7 @@ public async Task DI() IRepositoryComparerFactory factory = container.GetInstance(); var comparer = factory.Create(result); - var repo = new R { Name = "Rian", IsPinned = true,}; + var repo = new R { Name = "rrrr", IsPinned = true,}; var repo2 = new R { Name = "Coen", IsPinned = false, }; int r = comparer.Compare(repo, repo2); @@ -107,4 +107,5 @@ public class R : IRepository public bool IsPinned { get; set; } public bool HasUnpushedChanges { get; set; } public string[] Tags { get; set; } = Array.Empty(); + public List Remotes { get; } = new(0); } \ No newline at end of file From f1c5b0e7334cf6be07ec4ad45c4383a01e0f167b Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 29 Nov 2022 09:05:59 +0100 Subject: [PATCH 28/60] update --- .../Common/HardcodededMiniHumanizer.cs | 6 +----- src/RepoM.Api/Common/SystemClock.cs | 7 +++++++ .../RepositoryExpressionEvaluator.cs | 13 ++++++------- .../RepositorySpecificConfiguration.cs | 18 +++++++++--------- .../UtcToHumanizedLocalDateTimeConverter.cs | 2 +- .../Common/IClock.cs | 2 +- .../StatisticsService.cs | 9 ++++++++- tests/Tests/Helper/FakeClock.cs | 2 +- 8 files changed, 34 insertions(+), 25 deletions(-) rename src/{RepoM.Api => RepoM.Core.Plugin}/Common/IClock.cs (65%) diff --git a/src/RepoM.Api/Common/HardcodededMiniHumanizer.cs b/src/RepoM.Api/Common/HardcodededMiniHumanizer.cs index ac358df1..4cb163b7 100644 --- a/src/RepoM.Api/Common/HardcodededMiniHumanizer.cs +++ b/src/RepoM.Api/Common/HardcodededMiniHumanizer.cs @@ -1,16 +1,12 @@ namespace RepoM.Api.Common; using System; +using RepoM.Core.Plugin.Common; public class HardcodededMiniHumanizer : IHumanizer { private readonly IClock _clock; - public HardcodededMiniHumanizer() - : this(new SystemClock()) - { - } - public HardcodededMiniHumanizer(IClock clock) { _clock = clock ?? throw new ArgumentNullException(nameof(clock)); diff --git a/src/RepoM.Api/Common/SystemClock.cs b/src/RepoM.Api/Common/SystemClock.cs index 7c403999..255697d1 100644 --- a/src/RepoM.Api/Common/SystemClock.cs +++ b/src/RepoM.Api/Common/SystemClock.cs @@ -1,8 +1,15 @@ namespace RepoM.Api.Common; using System; +using RepoM.Core.Plugin.Common; public class SystemClock : IClock { + private SystemClock() + { + } + + public static SystemClock Instance { get; } = new(); + public DateTime Now => DateTime.Now; } \ No newline at end of file diff --git a/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs b/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs index 959b1770..76c29ff5 100644 --- a/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs +++ b/src/RepoM.Api/IO/ExpressionEvaluator/RepositoryExpressionEvaluator.cs @@ -6,7 +6,6 @@ namespace RepoM.Api.IO.ExpressionEvaluator; using ExpressionStringEvaluator.Methods; using ExpressionStringEvaluator.Parser; using ExpressionStringEvaluator.VariableProviders; -using RepoM.Api.Git; using RepoM.Core.Plugin.Repository; public class RepositoryExpressionEvaluator @@ -21,17 +20,17 @@ public RepositoryExpressionEvaluator(IEnumerable variableProv _expressionExecutor = new ExpressionExecutor(v, m); } - public string EvaluateStringExpression(string value, params Repository[] repository) + public string EvaluateStringExpression(string value, params IRepository[] repository) { return EvaluateStringExpression(value, repository.AsEnumerable()); } - public object? EvaluateValueExpression(string value, params Repository[] repository) + public object? EvaluateValueExpression(string value, params IRepository[] repository) { return EvaluateValueExpression(value, repository.AsEnumerable()); } - private object? EvaluateValueExpression(string value, IEnumerable repository) + private object? EvaluateValueExpression(string value, IEnumerable repository) { try { @@ -43,7 +42,7 @@ public string EvaluateStringExpression(string value, params Repository[] reposit } } - private string EvaluateStringExpression(string value, IEnumerable repository) + private string EvaluateStringExpression(string value, IEnumerable repository) { try { @@ -68,7 +67,7 @@ private string EvaluateStringExpression(string value, IEnumerable re } } - public bool EvaluateBooleanExpression(string? value, Repository? repository) + public bool EvaluateBooleanExpression(string? value, IRepository? repository) { if (string.IsNullOrWhiteSpace(value)) { @@ -87,7 +86,7 @@ public bool EvaluateBooleanExpression(string? value, Repository? repository) try { - Repository[] repositories = repository == null ? Array.Empty() : new[] { repository, }; + IRepository[] repositories = repository == null ? Array.Empty() : new[] { repository, }; object? result = _expressionExecutor.Execute(new RepositoryContext(repositories), value!); diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs index ef3c7431..d69db6e1 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs @@ -67,14 +67,14 @@ private string GetRepositoryActionsFilename(string basePath) throw new ConfigurationFileNotFoundException(failingFilename); } - public (Dictionary? envVars, List? Variables, List? actions, List? tags) Get(params Repository[] repositories) + public (Dictionary? envVars, List? Variables, List? actions, List? tags) Get(params IRepository[] repositories) { if (!repositories.Any()) { return (null, null, null, null); } - Repository? repository = repositories.FirstOrDefault(); //todo + IRepository? repository = repositories.FirstOrDefault(); //todo if (repository == null) { return (null, null, null, null); @@ -252,19 +252,19 @@ List EvaluateVariables(IEnumerable? vars) return (envVars, variables, actions, tags); } - private object? Evaluate(object? input, Repository? repository) + private object? Evaluate(object? input, IRepository? repository) { if (input is not string s) { return input; } - Repository[] repositories = repository == null ? Array.Empty() : new[] { repository, }; + IRepository[] repositories = repository == null ? Array.Empty() : new[] { repository, }; return _repoExpressionEvaluator.EvaluateValueExpression(s, repositories); } - private string EvaluateString(string? input, Repository? repository) + private string EvaluateString(string? input, IRepository? repository) { object? v = Evaluate(input, repository); if (v == null) @@ -275,7 +275,7 @@ private string EvaluateString(string? input, Repository? repository) return v.ToString(); } - private bool IsEnabled(string? booleanExpression, bool defaultWhenNullOrEmpty, Repository? repository) + private bool IsEnabled(string? booleanExpression, bool defaultWhenNullOrEmpty, IRepository? repository) { return string.IsNullOrWhiteSpace(booleanExpression) ? defaultWhenNullOrEmpty @@ -321,7 +321,7 @@ public IEnumerable GetTags(Repository repository) return GetTagsInner(repository).Distinct(); } - private IEnumerable GetTagsInner(Repository repository) + private IEnumerable GetTagsInner(IRepository repository) { List EvaluateVariables(IEnumerable? vars) { @@ -376,7 +376,7 @@ List EvaluateVariables(IEnumerable? vars) } } - private object? Evaluate(object? input, Repository repository) + private object? Evaluate(object? input, IRepository repository) { if (input is string s) { @@ -386,7 +386,7 @@ List EvaluateVariables(IEnumerable? vars) return input; } - private bool IsEnabled(string? booleanExpression, bool defaultWhenNullOrEmpty, Repository repository) + private bool IsEnabled(string? booleanExpression, bool defaultWhenNullOrEmpty, IRepository repository) { return string.IsNullOrWhiteSpace(booleanExpression) ? defaultWhenNullOrEmpty diff --git a/src/RepoM.App/Converters/UtcToHumanizedLocalDateTimeConverter.cs b/src/RepoM.App/Converters/UtcToHumanizedLocalDateTimeConverter.cs index 1df7363d..a2c85c00 100644 --- a/src/RepoM.App/Converters/UtcToHumanizedLocalDateTimeConverter.cs +++ b/src/RepoM.App/Converters/UtcToHumanizedLocalDateTimeConverter.cs @@ -11,7 +11,7 @@ public class UtcToHumanizedLocalDateTimeConverter : IValueConverter public UtcToHumanizedLocalDateTimeConverter() { - _humanizer = new HardcodededMiniHumanizer(); + _humanizer = new HardcodededMiniHumanizer(SystemClock.Instance); } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/src/RepoM.Api/Common/IClock.cs b/src/RepoM.Core.Plugin/Common/IClock.cs similarity index 65% rename from src/RepoM.Api/Common/IClock.cs rename to src/RepoM.Core.Plugin/Common/IClock.cs index f03a40bc..361beb73 100644 --- a/src/RepoM.Api/Common/IClock.cs +++ b/src/RepoM.Core.Plugin/Common/IClock.cs @@ -1,4 +1,4 @@ -namespace RepoM.Api.Common; +namespace RepoM.Core.Plugin.Common; using System; diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs index 4d1709b5..4f14ee48 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsService.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -3,13 +3,20 @@ namespace RepoM.Plugin.Statistics; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.Repository; public class StatisticsService { + private readonly IClock _clock; private readonly ReadOnlyCollection _empty = new List(0).AsReadOnly(); private readonly Dictionary> _recordings = new(); + public StatisticsService(IClock clock) + { + _clock = clock ?? throw new ArgumentNullException(nameof(clock)); + } + public void Record(IRepository repository) { if (!_recordings.TryGetValue(repository.SafePath, out List? list)) @@ -18,7 +25,7 @@ public void Record(IRepository repository) _recordings.TryAdd(repository.SafePath, list); } - list.Add(DateTime.Now); + list.Add(_clock.Now); } public IReadOnlyList GetRecordings(IRepository repository) diff --git a/tests/Tests/Helper/FakeClock.cs b/tests/Tests/Helper/FakeClock.cs index cce89439..77e32cad 100644 --- a/tests/Tests/Helper/FakeClock.cs +++ b/tests/Tests/Helper/FakeClock.cs @@ -1,7 +1,7 @@ namespace Tests.Helper; using System; -using RepoM.Api.Common; +using RepoM.Core.Plugin.Common; internal class FakeClock : IClock { From 4b721aa20a9a136b4791efc4a93e0aa74d30bd5b Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 29 Nov 2022 22:46:14 +0100 Subject: [PATCH 29/60] wip --- src/RepoM.Api/Common/AppSettings.cs | 2 + .../Common/FileAppSettingsService.cs | 18 ++++ src/RepoM.Api/Common/IAppSettingsService.cs | 2 + src/RepoM.App/App.xaml.cs | 3 +- src/RepoM.App/Controls/AcrylicContextMenu.cs | 2 + src/RepoM.App/MainWindow.xaml | 66 +++++++++++-- src/RepoM.App/MainWindowPageModel.cs | 93 +++++++++++++++++++ src/RepoM.App/RepositoryComparerAdapter.cs | 48 ++++++++++ src/RepoM.App/ViewModels/MenuItemViewModel.cs | 39 ++++++++ 9 files changed, 266 insertions(+), 7 deletions(-) create mode 100644 src/RepoM.App/ViewModels/MenuItemViewModel.cs diff --git a/src/RepoM.Api/Common/AppSettings.cs b/src/RepoM.Api/Common/AppSettings.cs index eb2d8b76..a152c130 100644 --- a/src/RepoM.Api/Common/AppSettings.cs +++ b/src/RepoM.Api/Common/AppSettings.cs @@ -11,7 +11,9 @@ public AppSettings() EnabledSearchProviders = new List(); SonarCloudPersonalAccessToken = string.Empty; AzureDevOps = AzureDevOpsOptions.Default; + SortKey = string.Empty; } + public string SortKey { get; set; } public AutoFetchMode AutoFetchMode { get; set; } diff --git a/src/RepoM.Api/Common/FileAppSettingsService.cs b/src/RepoM.Api/Common/FileAppSettingsService.cs index 89225893..f1ffa961 100644 --- a/src/RepoM.Api/Common/FileAppSettingsService.cs +++ b/src/RepoM.Api/Common/FileAppSettingsService.cs @@ -132,6 +132,24 @@ private string GetFileName() private AppSettings Settings => _settings ??= Load(); + + public string SortKey + { + get => Settings.SortKey; + set + { + if (value == Settings.SortKey) + { + return; + } + + Settings.SortKey = value; + + NotifyChange(); + Save(); + } + } + public AutoFetchMode AutoFetchMode { get => Settings.AutoFetchMode; diff --git a/src/RepoM.Api/Common/IAppSettingsService.cs b/src/RepoM.Api/Common/IAppSettingsService.cs index 69791251..cd0adfc8 100644 --- a/src/RepoM.Api/Common/IAppSettingsService.cs +++ b/src/RepoM.Api/Common/IAppSettingsService.cs @@ -28,5 +28,7 @@ public interface IAppSettingsService string AzureDevOpsBaseUrl { get; set; } + string SortKey { get; set; } + void RegisterInvalidationHandler(Action handler); } diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index 9173bc05..65aaa245 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -49,6 +49,7 @@ namespace RepoM.App; using RepoM.Api.RepositoryActions.Executors; using RepoM.App.RepositoryActions; using RepoM.App.RepositoryOrdering; +using RepoM.Core.Plugin.Common; /// /// Interaction logic for App.xaml @@ -225,7 +226,7 @@ private static void RegisterServices(Container container, IFileSystem fileSystem container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); - + container.RegisterInstance(SystemClock.Instance); container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); diff --git a/src/RepoM.App/Controls/AcrylicContextMenu.cs b/src/RepoM.App/Controls/AcrylicContextMenu.cs index b730a7cd..6934e356 100644 --- a/src/RepoM.App/Controls/AcrylicContextMenu.cs +++ b/src/RepoM.App/Controls/AcrylicContextMenu.cs @@ -12,4 +12,6 @@ protected override void OnOpened(RoutedEventArgs e) AcrylicHelper.EnableBlur(this); } + + } \ No newline at end of file diff --git a/src/RepoM.App/MainWindow.xaml b/src/RepoM.App/MainWindow.xaml index 8b3d805f..632a153c 100644 --- a/src/RepoM.App/MainWindow.xaml +++ b/src/RepoM.App/MainWindow.xaml @@ -8,6 +8,7 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:converters="clr-namespace:RepoM.App.Converters" xmlns:controls="clr-namespace:RepoM.App.Controls" + xmlns:app="clr-namespace:RepoM.App" TextElement.Foreground="{DynamicResource MaterialDesignBody}" TextElement.FontWeight="Regular" TextElement.FontSize="12" @@ -107,10 +108,15 @@ Grid.Column="1" Foreground="{DynamicResource MaterialDesignBody}" Style="{DynamicResource MaterialDesignFlatButton}"> - - - - + + + + + + @@ -119,10 +125,58 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/src/RepoM.App/MainWindowPageModel.cs b/src/RepoM.App/MainWindowPageModel.cs index 3696f9ce..d5794dfc 100644 --- a/src/RepoM.App/MainWindowPageModel.cs +++ b/src/RepoM.App/MainWindowPageModel.cs @@ -1,10 +1,100 @@ namespace RepoM.App; using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; +using Lucene.Net.Util.Packed; +using Microsoft.Xaml.Behaviors.Core; using RepoM.Api.Common; using RepoM.Api.Git.AutoFetch; +using RepoM.App.ViewModels; + + +public class SortMenuItemViewModel : MenuItemViewModel +{ + private readonly IAppSettingsService _appSettingsService; + private readonly string _title; + + public SortMenuItemViewModel( + IAppSettingsService appSettingsService, + string title) + { + _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + _title = title; + + Header = title; + Command = new DelegateCommand + { + CommandAction = () => + { + _appSettingsService.SortKey = title; + }, + CanExecuteFunc = () => _appSettingsService.SortKey != title, + }; + IsCheckable = true; + IsChecked = _appSettingsService.SortKey == title; + } + + public override bool IsChecked + { + get => _appSettingsService.SortKey == _title; + set => Command?.Execute(null); + } +} + +public class OrderingsViewModel : List +{ + private readonly IAppSettingsService _appSettingsService; + + public OrderingsViewModel(IAppSettingsService appSettingsService) + { + _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + + Add(new SortMenuItemViewModel(_appSettingsService, "DRC First") + { + Header = "DRC first", + IsCheckable = false, + IsChecked = false, + Command = new DelegateCommand + { + CommandAction = () => _appSettingsService.SortKey = "", + CanExecuteFunc = () => _appSettingsService.SortKey != "", + } + }); + Add(new() + { + Header = "Private 1", + IsCheckable = true, + IsChecked = true, + }); + Add(new() + { + Header = "Private 2", + IsCheckable = true, + IsChecked = false, + }); + + + // public AutoFetchMode AutoFetchMode + // { + // get => _appSettingsService.AutoFetchMode; + // set + // { + // _appSettingsService.AutoFetchMode = value; + // + // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchMode))); + // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchOff))); + // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchDiscretely))); + // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchAdequate))); + // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchAggressive))); + // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(EnabledSearchRepoEverything))); + // } + // } + // }; +} +} public class MainWindowPageModel : INotifyPropertyChanged { @@ -14,8 +104,11 @@ public class MainWindowPageModel : INotifyPropertyChanged public MainWindowPageModel(IAppSettingsService appSettingsService) { _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + Orderings = new OrderingsViewModel(_appSettingsService); } + public OrderingsViewModel Orderings { get; } + public AutoFetchMode AutoFetchMode { get => _appSettingsService.AutoFetchMode; diff --git a/src/RepoM.App/RepositoryComparerAdapter.cs b/src/RepoM.App/RepositoryComparerAdapter.cs index f6e4722e..5b8f031a 100644 --- a/src/RepoM.App/RepositoryComparerAdapter.cs +++ b/src/RepoM.App/RepositoryComparerAdapter.cs @@ -2,9 +2,57 @@ namespace RepoM.App; using System; using System.Collections; +using System.Collections.Generic; +using System.Linq; +using RepoM.Api.Common; using RepoM.Api.Git; using RepoM.Core.Plugin.RepositoryOrdering; +internal class RepositoryComparerManager +{ + private readonly IAppSettingsService _appSettingsService; + private ComparerComposition _comparer; + + public RepositoryComparerManager(IAppSettingsService appSettingsService) + { + _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + _comparer = new ComparerComposition(new Dictionary()); + ViewModel = new OrderingsViewModel(appSettingsService); + } + + public IComparer Comparer => _comparer; + + public OrderingsViewModel ViewModel { get; } +} + +internal class ComparerComposition : IComparer +{ + private readonly Dictionary _comparers; + private IComparer _selected; + + public ComparerComposition(Dictionary namedComparers) + { + _comparers = namedComparers; + _selected = _comparers.First().Value; + } + + public bool SetComparer(string key) + { + if (_comparers.TryGetValue(key, out IComparer? value)) + { + _selected = value; + return true; + } + + return false; + } + + public int Compare(object? x, object? y) + { + IComparer comparer = _selected; + return comparer.Compare(x, y); + } +} internal class RepositoryComparerAdapter : IComparer { private readonly IRepositoryComparer _comparer; diff --git a/src/RepoM.App/ViewModels/MenuItemViewModel.cs b/src/RepoM.App/ViewModels/MenuItemViewModel.cs new file mode 100644 index 00000000..3be8742d --- /dev/null +++ b/src/RepoM.App/ViewModels/MenuItemViewModel.cs @@ -0,0 +1,39 @@ +namespace RepoM.App.ViewModels; + +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Windows.Input; + +// https://stackoverflow.com/questions/5912687/styling-contextmenu-and-contextmenu-items +// https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/contextmenu-styles-and-templates?view=netframeworkdesktop-4.8 +// https://itecnote.com/tecnote/wpf-how-to-bind-an-observablecollection-of-viewmodels-to-a-menuitem/ +public class MenuItemViewModel : INotifyPropertyChanged +{ + public string Header { get; set; } = string.Empty; + + public bool IsCheckable { get; set; } + + public virtual bool IsChecked { get; set; } + + public ICommand Command { get; set; } + + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null) + { + if (EqualityComparer.Default.Equals(field, value)) + { + return false; + } + + field = value; + OnPropertyChanged(propertyName); + return true; + } +} \ No newline at end of file From 4a8d65ae26810e308a9e01b25aa01311c188aab1 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 29 Nov 2022 23:26:50 +0100 Subject: [PATCH 30/60] .. --- src/RepoM.App/RepositoryComparerAdapter.cs | 48 ++++++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/src/RepoM.App/RepositoryComparerAdapter.cs b/src/RepoM.App/RepositoryComparerAdapter.cs index 5b8f031a..7881ed1d 100644 --- a/src/RepoM.App/RepositoryComparerAdapter.cs +++ b/src/RepoM.App/RepositoryComparerAdapter.cs @@ -8,37 +8,66 @@ namespace RepoM.App; using RepoM.Api.Git; using RepoM.Core.Plugin.RepositoryOrdering; -internal class RepositoryComparerManager +public interface IRepositoryComparerManager +{ + event EventHandler? SelectedRepositoryComparerKeyChanged; + + IComparer Comparer { get; } + + IReadOnlyList RepositoryComparerKeys { get; } + + bool SetRepositoryComparer(string key); +} + +internal class RepositoryComparerManager : IRepositoryComparerManager { private readonly IAppSettingsService _appSettingsService; - private ComparerComposition _comparer; + private readonly ComparerComposition _comparer; + private readonly List _repositoryComparerKeys; public RepositoryComparerManager(IAppSettingsService appSettingsService) { _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); _comparer = new ComparerComposition(new Dictionary()); - ViewModel = new OrderingsViewModel(appSettingsService); + SelectedRepositoryComparerKey = string.Empty; + _repositoryComparerKeys = new List(); } + public event EventHandler? SelectedRepositoryComparerKeyChanged; + public IComparer Comparer => _comparer; - public OrderingsViewModel ViewModel { get; } + public string SelectedRepositoryComparerKey { get; private set; } + + public IReadOnlyList RepositoryComparerKeys => _repositoryComparerKeys; + + public bool SetRepositoryComparer(string key) + { + if (_comparer.SetComparer(key)) + { + SelectedRepositoryComparerKey = key; + SelectedRepositoryComparerKeyChanged?.Invoke(this, key); + return true; + } + + return false; + } } internal class ComparerComposition : IComparer { - private readonly Dictionary _comparers; + private readonly Dictionary _namedComparers; private IComparer _selected; - public ComparerComposition(Dictionary namedComparers) + public ComparerComposition(Dictionary namedNamedComparers) { - _comparers = namedComparers; - _selected = _comparers.First().Value; + _namedComparers = namedNamedComparers; + _selected = _namedComparers.First().Value; } public bool SetComparer(string key) { - if (_comparers.TryGetValue(key, out IComparer? value)) + if (_namedComparers.TryGetValue(key, out IComparer? value)) { _selected = value; return true; @@ -53,6 +82,7 @@ public int Compare(object? x, object? y) return comparer.Compare(x, y); } } + internal class RepositoryComparerAdapter : IComparer { private readonly IRepositoryComparer _comparer; From f6e9a46d29a496de864753da1cb355ba85ee4bbf Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 29 Nov 2022 23:27:03 +0100 Subject: [PATCH 31/60] .. --- src/RepoM.App/MainWindowPageModel.cs | 69 +++++++------------ src/RepoM.App/RepositoryComparerAdapter.cs | 2 +- src/RepoM.App/ViewModels/MenuItemViewModel.cs | 2 - 3 files changed, 27 insertions(+), 46 deletions(-) diff --git a/src/RepoM.App/MainWindowPageModel.cs b/src/RepoM.App/MainWindowPageModel.cs index d5794dfc..d1e9bba8 100644 --- a/src/RepoM.App/MainWindowPageModel.cs +++ b/src/RepoM.App/MainWindowPageModel.cs @@ -2,11 +2,8 @@ namespace RepoM.App; using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; -using Lucene.Net.Util.Packed; -using Microsoft.Xaml.Behaviors.Core; using RepoM.Api.Common; using RepoM.Api.Git.AutoFetch; using RepoM.App.ViewModels; @@ -14,67 +11,53 @@ namespace RepoM.App; public class SortMenuItemViewModel : MenuItemViewModel { - private readonly IAppSettingsService _appSettingsService; - private readonly string _title; + private readonly Func _isSelectedFunc; + private readonly Action _setKeyFunc; public SortMenuItemViewModel( - IAppSettingsService appSettingsService, + Func isSelectedFunc, + Action setKeyFunc, string title) { - _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); - _title = title; + _isSelectedFunc = isSelectedFunc ?? throw new ArgumentNullException(nameof(isSelectedFunc)); + _setKeyFunc = setKeyFunc ?? throw new ArgumentNullException(nameof(setKeyFunc)); Header = title; - Command = new DelegateCommand - { - CommandAction = () => - { - _appSettingsService.SortKey = title; - }, - CanExecuteFunc = () => _appSettingsService.SortKey != title, - }; IsCheckable = true; - IsChecked = _appSettingsService.SortKey == title; } public override bool IsChecked { - get => _appSettingsService.SortKey == _title; - set => Command?.Execute(null); + get => _isSelectedFunc.Invoke(); + set => _setKeyFunc.Invoke(); } } public class OrderingsViewModel : List { + private readonly IRepositoryComparerManager _repositoryComparerManager; private readonly IAppSettingsService _appSettingsService; - public OrderingsViewModel(IAppSettingsService appSettingsService) + public OrderingsViewModel( + IRepositoryComparerManager repositoryComparerManager, + IAppSettingsService appSettingsService) { - _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + _repositoryComparerManager = repositoryComparerManager ?? throw new ArgumentNullException(nameof(repositoryComparerManager)); - Add(new SortMenuItemViewModel(_appSettingsService, "DRC First") - { - Header = "DRC first", - IsCheckable = false, - IsChecked = false, - Command = new DelegateCommand - { - CommandAction = () => _appSettingsService.SortKey = "", - CanExecuteFunc = () => _appSettingsService.SortKey != "", - } - }); - Add(new() - { - Header = "Private 1", - IsCheckable = true, - IsChecked = true, - }); - Add(new() + + _repositoryComparerManager.SelectedRepositoryComparerKeyChanged += (sender, key) => { - Header = "Private 2", - IsCheckable = true, - IsChecked = false, - }); + + }; + _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + + AddRange( + _repositoryComparerManager + .RepositoryComparerKeys + .Select(name => new SortMenuItemViewModel( + () => _repositoryComparerManager.SelectedRepositoryComparerKey == name, + () => _repositoryComparerManager.SetRepositoryComparer(name), + name))); // public AutoFetchMode AutoFetchMode diff --git a/src/RepoM.App/RepositoryComparerAdapter.cs b/src/RepoM.App/RepositoryComparerAdapter.cs index 7881ed1d..fdea5505 100644 --- a/src/RepoM.App/RepositoryComparerAdapter.cs +++ b/src/RepoM.App/RepositoryComparerAdapter.cs @@ -15,7 +15,7 @@ public interface IRepositoryComparerManager IComparer Comparer { get; } IReadOnlyList RepositoryComparerKeys { get; } - + string SelectedRepositoryComparerKey { get; } bool SetRepositoryComparer(string key); } diff --git a/src/RepoM.App/ViewModels/MenuItemViewModel.cs b/src/RepoM.App/ViewModels/MenuItemViewModel.cs index 3be8742d..e7c9c563 100644 --- a/src/RepoM.App/ViewModels/MenuItemViewModel.cs +++ b/src/RepoM.App/ViewModels/MenuItemViewModel.cs @@ -16,8 +16,6 @@ public class MenuItemViewModel : INotifyPropertyChanged public virtual bool IsChecked { get; set; } - public ICommand Command { get; set; } - public event PropertyChangedEventHandler? PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) From 3c3627473d9753208c8308a465176821185f0541 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 30 Nov 2022 09:23:39 +0100 Subject: [PATCH 32/60] wip --- src/RepoM.App/App.xaml.cs | 1 + src/RepoM.App/MainWindow.xaml.cs | 14 ++- src/RepoM.App/MainWindowPageModel.cs | 69 +++++------ src/RepoM.App/RepositoryComparerAdapter.cs | 109 ------------------ .../RepositoryOrdering/ComparerComposition.cs | 34 ++++++ .../IRepositoryComparerManager.cs | 16 +++ .../RepositoryComparerAdapter.cs | 31 +++++ .../RepositoryComparerManager.cs | 81 +++++++++++++ 8 files changed, 202 insertions(+), 153 deletions(-) delete mode 100644 src/RepoM.App/RepositoryComparerAdapter.cs create mode 100644 src/RepoM.App/RepositoryOrdering/ComparerComposition.cs create mode 100644 src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs create mode 100644 src/RepoM.App/RepositoryOrdering/RepositoryComparerAdapter.cs create mode 100644 src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index 65aaa245..e4293a75 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -229,6 +229,7 @@ private static void RegisterServices(Container container, IFileSystem fileSystem container.RegisterInstance(SystemClock.Instance); container.Register(Lifestyle.Singleton); container.Register(Lifestyle.Singleton); + container.Register(Lifestyle.Singleton); container.Collection.Append(Lifestyle.Singleton); container.RegisterInstance(fileSystem); diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index 2372741c..3e268ec5 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -19,6 +19,7 @@ namespace RepoM.App; using RepoM.Api.IO; using RepoM.App.Controls; using RepoM.App.RepositoryActions; +using RepoM.App.RepositoryOrdering; using RepoM.App.Services; using RepoM.Core.Plugin.RepositoryOrdering; using SourceChord.FluentWPF; @@ -51,16 +52,17 @@ public MainWindow( IAppDataPathProvider appDataPathProvider, IRepositorySearch repositorySearch, IFileSystem fileSystem, - ICompareSettingsService compareSettingsService, - IRepositoryComparerFactory repositoryComparerFactory, - ActionExecutor executor) + ActionExecutor executor, + IRepositoryComparerManager repositoryComparerManager, + IThreadDispatcher threadDispatcher) { _translationService = translationService; InitializeComponent(); AcrylicWindow.SetAcrylicWindowStyle(this, AcrylicWindowStyle.None); - DataContext = new MainWindowPageModel(appSettingsService); + var orderingsViewModel = new OrderingsViewModel(repositoryComparerManager, threadDispatcher); + DataContext = new MainWindowPageModel(appSettingsService, orderingsViewModel); SettingsMenu.DataContext = DataContext; // this is out of the visual tree _monitor = repositoryMonitor as DefaultRepositoryMonitor; @@ -82,8 +84,8 @@ public MainWindow( var view = (ListCollectionView)CollectionViewSource.GetDefaultView(aggregator.Repositories); ((ICollectionView)view).CollectionChanged += View_CollectionChanged; view.Filter = FilterRepositories; - view.CustomSort = new RepositoryComparerAdapter(repositoryComparerFactory.Create(compareSettingsService.Configuration)); - // view.Refresh(); // todo refresh on change of value in on of the characteristics sorting is based on. + view.CustomSort = repositoryComparerManager.Comparer; + repositoryComparerManager.SelectedRepositoryComparerKeyChanged += (_, _) => view.Refresh(); AssemblyName? appName = Assembly.GetEntryAssembly()?.GetName(); txtHelpCaption.Text = appName?.Name + " " + appName?.Version?.ToString(2); diff --git a/src/RepoM.App/MainWindowPageModel.cs b/src/RepoM.App/MainWindowPageModel.cs index d1e9bba8..0516c19a 100644 --- a/src/RepoM.App/MainWindowPageModel.cs +++ b/src/RepoM.App/MainWindowPageModel.cs @@ -6,6 +6,7 @@ namespace RepoM.App; using System.Linq; using RepoM.Api.Common; using RepoM.Api.Git.AutoFetch; +using RepoM.App.RepositoryOrdering; using RepoM.App.ViewModels; @@ -31,52 +32,44 @@ public override bool IsChecked get => _isSelectedFunc.Invoke(); set => _setKeyFunc.Invoke(); } + + public void Poke() + { + OnPropertyChanged(nameof(IsChecked)); + } } public class OrderingsViewModel : List { - private readonly IRepositoryComparerManager _repositoryComparerManager; - private readonly IAppSettingsService _appSettingsService; - - public OrderingsViewModel( - IRepositoryComparerManager repositoryComparerManager, - IAppSettingsService appSettingsService) + public OrderingsViewModel(IRepositoryComparerManager repositoryComparerManager, IThreadDispatcher threadDispatcher) { - _repositoryComparerManager = repositoryComparerManager ?? throw new ArgumentNullException(nameof(repositoryComparerManager)); + if (repositoryComparerManager == null) + { + throw new ArgumentNullException(nameof(repositoryComparerManager)); + } + if (threadDispatcher == null) + { + throw new ArgumentNullException(nameof(threadDispatcher)); + } - _repositoryComparerManager.SelectedRepositoryComparerKeyChanged += (sender, key) => + repositoryComparerManager.SelectedRepositoryComparerKeyChanged += (_, _) => { - + foreach (MenuItemViewModel item in this) + { + if (item is SortMenuItemViewModel sortMenuItemViewModel) + { + threadDispatcher.Invoke(() => sortMenuItemViewModel.Poke()); + } + } }; - _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); - AddRange( - _repositoryComparerManager - .RepositoryComparerKeys - .Select(name => new SortMenuItemViewModel( - () => _repositoryComparerManager.SelectedRepositoryComparerKey == name, - () => _repositoryComparerManager.SetRepositoryComparer(name), - name))); - - - // public AutoFetchMode AutoFetchMode - // { - // get => _appSettingsService.AutoFetchMode; - // set - // { - // _appSettingsService.AutoFetchMode = value; - // - // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchMode))); - // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchOff))); - // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchDiscretely))); - // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchAdequate))); - // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AutoFetchAggressive))); - // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(EnabledSearchRepoEverything))); - // } - // } - // }; -} + AddRange(repositoryComparerManager.RepositoryComparerKeys.Select(name => + new SortMenuItemViewModel( + () => repositoryComparerManager.SelectedRepositoryComparerKey == name, + () => repositoryComparerManager.SetRepositoryComparer(name), + name))); + } } public class MainWindowPageModel : INotifyPropertyChanged @@ -84,10 +77,10 @@ public class MainWindowPageModel : INotifyPropertyChanged private readonly IAppSettingsService _appSettingsService; public event PropertyChangedEventHandler? PropertyChanged; - public MainWindowPageModel(IAppSettingsService appSettingsService) + public MainWindowPageModel(IAppSettingsService appSettingsService, OrderingsViewModel orderingsViewModel) { _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); - Orderings = new OrderingsViewModel(_appSettingsService); + Orderings = orderingsViewModel; } public OrderingsViewModel Orderings { get; } diff --git a/src/RepoM.App/RepositoryComparerAdapter.cs b/src/RepoM.App/RepositoryComparerAdapter.cs deleted file mode 100644 index fdea5505..00000000 --- a/src/RepoM.App/RepositoryComparerAdapter.cs +++ /dev/null @@ -1,109 +0,0 @@ -namespace RepoM.App; - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using RepoM.Api.Common; -using RepoM.Api.Git; -using RepoM.Core.Plugin.RepositoryOrdering; - -public interface IRepositoryComparerManager -{ - event EventHandler? SelectedRepositoryComparerKeyChanged; - - IComparer Comparer { get; } - - IReadOnlyList RepositoryComparerKeys { get; } - string SelectedRepositoryComparerKey { get; } - bool SetRepositoryComparer(string key); -} - -internal class RepositoryComparerManager : IRepositoryComparerManager -{ - private readonly IAppSettingsService _appSettingsService; - private readonly ComparerComposition _comparer; - private readonly List _repositoryComparerKeys; - - public RepositoryComparerManager(IAppSettingsService appSettingsService) - { - _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); - _comparer = new ComparerComposition(new Dictionary()); - SelectedRepositoryComparerKey = string.Empty; - _repositoryComparerKeys = new List(); - } - - public event EventHandler? SelectedRepositoryComparerKeyChanged; - - public IComparer Comparer => _comparer; - - public string SelectedRepositoryComparerKey { get; private set; } - - public IReadOnlyList RepositoryComparerKeys => _repositoryComparerKeys; - - public bool SetRepositoryComparer(string key) - { - if (_comparer.SetComparer(key)) - { - SelectedRepositoryComparerKey = key; - SelectedRepositoryComparerKeyChanged?.Invoke(this, key); - return true; - } - - return false; - } -} - -internal class ComparerComposition : IComparer -{ - private readonly Dictionary _namedComparers; - private IComparer _selected; - - public ComparerComposition(Dictionary namedNamedComparers) - { - _namedComparers = namedNamedComparers; - _selected = _namedComparers.First().Value; - } - - public bool SetComparer(string key) - { - if (_namedComparers.TryGetValue(key, out IComparer? value)) - { - _selected = value; - return true; - } - - return false; - } - - public int Compare(object? x, object? y) - { - IComparer comparer = _selected; - return comparer.Compare(x, y); - } -} - -internal class RepositoryComparerAdapter : IComparer -{ - private readonly IRepositoryComparer _comparer; - - public RepositoryComparerAdapter(IRepositoryComparer comparer) - { - _comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); - } - - public int Compare(object? x, object? y) - { - if (x is IRepositoryView xView && y is IRepositoryView yView) - { - return Compare(xView, yView); - } - - return 0; - } - - private int Compare(IRepositoryView x, IRepositoryView y) - { - return _comparer.Compare(x.Repository, y.Repository); - } -} \ No newline at end of file diff --git a/src/RepoM.App/RepositoryOrdering/ComparerComposition.cs b/src/RepoM.App/RepositoryOrdering/ComparerComposition.cs new file mode 100644 index 00000000..b76de040 --- /dev/null +++ b/src/RepoM.App/RepositoryOrdering/ComparerComposition.cs @@ -0,0 +1,34 @@ +namespace RepoM.App.RepositoryOrdering; + +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +internal class ComparerComposition : IComparer +{ + private readonly Dictionary _namedComparers; + private IComparer _selected; + + public ComparerComposition(Dictionary namedNamedComparers) + { + _namedComparers = namedNamedComparers; + _selected = _namedComparers.First().Value; + } + + public bool SetComparer(string key) + { + if (_namedComparers.TryGetValue(key, out IComparer? value)) + { + _selected = value; + return true; + } + + return false; + } + + public int Compare(object? x, object? y) + { + IComparer comparer = _selected; + return comparer.Compare(x, y); + } +} \ No newline at end of file diff --git a/src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs b/src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs new file mode 100644 index 00000000..937c24bb --- /dev/null +++ b/src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs @@ -0,0 +1,16 @@ +namespace RepoM.App.RepositoryOrdering; + +using System; +using System.Collections; +using System.Collections.Generic; + +public interface IRepositoryComparerManager +{ + event EventHandler? SelectedRepositoryComparerKeyChanged; + + IComparer Comparer { get; } + + IReadOnlyList RepositoryComparerKeys { get; } + string SelectedRepositoryComparerKey { get; } + bool SetRepositoryComparer(string key); +} \ No newline at end of file diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryComparerAdapter.cs b/src/RepoM.App/RepositoryOrdering/RepositoryComparerAdapter.cs new file mode 100644 index 00000000..c1dbe802 --- /dev/null +++ b/src/RepoM.App/RepositoryOrdering/RepositoryComparerAdapter.cs @@ -0,0 +1,31 @@ +namespace RepoM.App.RepositoryOrdering; + +using System; +using System.Collections; +using RepoM.Api.Git; +using RepoM.Core.Plugin.RepositoryOrdering; + +internal class RepositoryComparerAdapter : IComparer +{ + private readonly IRepositoryComparer _comparer; + + public RepositoryComparerAdapter(IRepositoryComparer comparer) + { + _comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); + } + + public int Compare(object? x, object? y) + { + if (x is IRepositoryView xView && y is IRepositoryView yView) + { + return Compare(xView, yView); + } + + return 0; + } + + private int Compare(IRepositoryView x, IRepositoryView y) + { + return _comparer.Compare(x.Repository, y.Repository); + } +} \ No newline at end of file diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs new file mode 100644 index 00000000..f9d21822 --- /dev/null +++ b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs @@ -0,0 +1,81 @@ +namespace RepoM.App.RepositoryOrdering; + +using System; +using System.Collections; +using System.Collections.Generic; +using RepoM.Api.Common; +using RepoM.Api.Ordering.Az; +using RepoM.Api.Ordering.Composition; +using RepoM.Api.Ordering.Label; +using RepoM.Api.Ordering.Score; +using RepoM.Core.Plugin.RepositoryOrdering; + +internal class RepositoryComparerManager : IRepositoryComparerManager +{ + private readonly IAppSettingsService _appSettingsService; + private readonly ComparerComposition _comparer; + private readonly List _repositoryComparerKeys; + + public RepositoryComparerManager( + IAppSettingsService appSettingsService, + ICompareSettingsService compareSettingsService, + IRepositoryComparerFactory repositoryComparerFactory) + { + _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + + if (compareSettingsService == null) + { + throw new ArgumentNullException(nameof(compareSettingsService)); + } + + if (repositoryComparerFactory == null) + { + throw new ArgumentNullException(nameof(repositoryComparerFactory)); + } + + _repositoryComparerKeys = new List + { + "Default", + "Prive", + "Config", + }; + + _comparer = new ComparerComposition( + new Dictionary + { + { "Default", new RepositoryComparerAdapter(new AzComparer(1, "Name")) }, + { "Prive", new RepositoryComparerAdapter( + new CompositionComparer( + new IRepositoryComparer[] + { + new ScoreComparer(new TagScoreCalculator("Prive", 1)), + new ScoreComparer(new TagScoreCalculator("TIS", 1)), + new AzComparer(1, "Name"), + }))}, + { "Config", new RepositoryComparerAdapter(repositoryComparerFactory.Create(compareSettingsService.Configuration)) }, + }); + + SelectedRepositoryComparerKey = "Default"; + } + + public event EventHandler? SelectedRepositoryComparerKeyChanged; + + public IComparer Comparer => _comparer; + + public string SelectedRepositoryComparerKey { get; private set; } + + public IReadOnlyList RepositoryComparerKeys => _repositoryComparerKeys; + + public bool SetRepositoryComparer(string key) + { + if (!_comparer.SetComparer(key)) + { + return false; + } + + SelectedRepositoryComparerKey = key; + SelectedRepositoryComparerKeyChanged?.Invoke(this, key); + return true; + + } +} \ No newline at end of file From 496b7332bbb47a5ca50a162b1805bead77c0f0cf Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 30 Nov 2022 12:08:23 +0100 Subject: [PATCH 33/60] update --- .../Common/FileAppSettingsService.cs | 14 ++--- src/RepoM.Api/Common/IAppSettingsService.cs | 2 +- .../IRepositoryComparerManager.cs | 2 + .../RepositoryComparerManager.cs | 61 +++++++++++-------- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/RepoM.Api/Common/FileAppSettingsService.cs b/src/RepoM.Api/Common/FileAppSettingsService.cs index f1ffa961..3367f803 100644 --- a/src/RepoM.Api/Common/FileAppSettingsService.cs +++ b/src/RepoM.Api/Common/FileAppSettingsService.cs @@ -17,7 +17,8 @@ public class FilesICompareSettingsService : ICompareSettingsService private readonly IFileSystem _fileSystem; private readonly IEnumerable _registrations; private readonly IAppDataPathProvider _appDataPathProvider; - private IRepositoriesComparerConfiguration? _settings; + private Dictionary? _configuration; + public FilesICompareSettingsService(IAppDataPathProvider appDataPathProvider, IFileSystem fileSystem, IEnumerable registrations) { @@ -26,27 +27,27 @@ public FilesICompareSettingsService(IAppDataPathProvider appDataPathProvider, IF _appDataPathProvider = appDataPathProvider ?? throw new ArgumentNullException(nameof(appDataPathProvider)); } - public IRepositoriesComparerConfiguration Configuration => _settings ??= Load(); + public Dictionary Configuration => _configuration ??= Load(); + private string GetFileName() { return Path.Combine(_appDataPathProvider.GetAppDataPath(), "RepoM.Ordering.yaml"); } - private IRepositoriesComparerConfiguration Load() + private Dictionary Load() { var file = GetFileName(); if (!_fileSystem.File.Exists(file)) { - throw new Exception("File doesnot exist"); + throw new Exception("File doesn't exist"); } try { var yml = _fileSystem.File.ReadAllText(file); - DeserializerBuilder builder = new DeserializerBuilder() .WithNamingConvention(HyphenatedNamingConvention.Instance); @@ -58,14 +59,13 @@ private IRepositoriesComparerConfiguration Load() IDeserializer deserializer = builder.Build(); - return deserializer.Deserialize(yml); + return deserializer.Deserialize>(yml); } catch { throw; /* Our app settings are not critical. For our purposes, we want to ignore IO exceptions */ } - } } diff --git a/src/RepoM.Api/Common/IAppSettingsService.cs b/src/RepoM.Api/Common/IAppSettingsService.cs index cd0adfc8..e49c1b0e 100644 --- a/src/RepoM.Api/Common/IAppSettingsService.cs +++ b/src/RepoM.Api/Common/IAppSettingsService.cs @@ -7,7 +7,7 @@ namespace RepoM.Api.Common; public interface ICompareSettingsService { - IRepositoriesComparerConfiguration Configuration { get; } + Dictionary Configuration { get; } } public interface IAppSettingsService diff --git a/src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs b/src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs index 937c24bb..0b9c0544 100644 --- a/src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs +++ b/src/RepoM.App/RepositoryOrdering/IRepositoryComparerManager.cs @@ -11,6 +11,8 @@ public interface IRepositoryComparerManager IComparer Comparer { get; } IReadOnlyList RepositoryComparerKeys { get; } + string SelectedRepositoryComparerKey { get; } + bool SetRepositoryComparer(string key); } \ No newline at end of file diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs index f9d21822..b2436cce 100644 --- a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs +++ b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs @@ -3,12 +3,11 @@ namespace RepoM.App.RepositoryOrdering; using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using RepoM.Api.Common; using RepoM.Api.Ordering.Az; -using RepoM.Api.Ordering.Composition; -using RepoM.Api.Ordering.Label; -using RepoM.Api.Ordering.Score; using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; internal class RepositoryComparerManager : IRepositoryComparerManager { @@ -33,29 +32,43 @@ public RepositoryComparerManager( throw new ArgumentNullException(nameof(repositoryComparerFactory)); } - _repositoryComparerKeys = new List - { - "Default", - "Prive", - "Config", - }; + Dictionary multipleConfigurations = new (); + var comparers = new Dictionary(); - _comparer = new ComparerComposition( - new Dictionary + try + { + multipleConfigurations = compareSettingsService.Configuration; + } + catch (Exception e) + { + Console.WriteLine(e); + } + + foreach ((var key, IRepositoriesComparerConfiguration config) in multipleConfigurations) + { + try + { + if (!comparers.TryAdd(key, new RepositoryComparerAdapter(repositoryComparerFactory.Create(config)))) + { + // swallow + } + } + catch (Exception) { - { "Default", new RepositoryComparerAdapter(new AzComparer(1, "Name")) }, - { "Prive", new RepositoryComparerAdapter( - new CompositionComparer( - new IRepositoryComparer[] - { - new ScoreComparer(new TagScoreCalculator("Prive", 1)), - new ScoreComparer(new TagScoreCalculator("TIS", 1)), - new AzComparer(1, "Name"), - }))}, - { "Config", new RepositoryComparerAdapter(repositoryComparerFactory.Create(compareSettingsService.Configuration)) }, - }); - - SelectedRepositoryComparerKey = "Default"; + // swallow + } + } + + if (comparers.Count == 0) + { + comparers.Add("Default", new RepositoryComparerAdapter(new AzComparer(1, "Name"))); + } + + _comparer = new ComparerComposition(comparers); + + _repositoryComparerKeys = comparers.Select(x => x.Key).ToList(); + + SelectedRepositoryComparerKey = _repositoryComparerKeys.First(); } public event EventHandler? SelectedRepositoryComparerKeyChanged; From c9164884ad582192eabe8f0f4e4419aa9e202d10 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 30 Nov 2022 14:55:08 +0100 Subject: [PATCH 34/60] . --- tests/Yaml.Poc.Tests/DI/Class1.cs | 59 ------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 tests/Yaml.Poc.Tests/DI/Class1.cs diff --git a/tests/Yaml.Poc.Tests/DI/Class1.cs b/tests/Yaml.Poc.Tests/DI/Class1.cs deleted file mode 100644 index 83d2aef5..00000000 --- a/tests/Yaml.Poc.Tests/DI/Class1.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace Yaml.Poc.Tests.DI; - -using System.Threading.Tasks; -using System.Threading; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using RepoM.Core.Plugin.RepositoryOrdering; -using SimpleInjector; -public interface IQuery -{ -} - -[DebuggerDisplay("{QueryType.Name,nq}")] -public sealed class QueryInfo -{ - public QueryInfo(Type queryType) - { - QueryType = queryType; - ResultType = DetermineResultTypes(queryType).Single(); - } - - public Type QueryType { get; } - - public Type ResultType { get; } - - public static bool IsQuery(Type type) - { - return DetermineResultTypes(type).Any(); - } - - private static IEnumerable DetermineResultTypes(Type type) - { - return from interfaceType in type.GetInterfaces() - where interfaceType.IsGenericType - where interfaceType.GetGenericTypeDefinition() == typeof(IQuery<>) - select interfaceType.GetGenericArguments()[0]; - } -} - -public class QueryProcessor -{ - private readonly Container _container; - - public QueryProcessor(Container container) - { - this._container = container; - } - - public async Task ExecuteQueryAsync(IQuery query, CancellationToken ct = default) - { - Type handlerType = typeof(IRepositoryScoreCalculatorFactory<>).MakeGenericType(query.GetType()); - - dynamic handler = _container.GetInstance(handlerType); - - return await handler.HandleAsync((dynamic)query, null, ct); - } -} \ No newline at end of file From beaf2181ec263755ae389905af18340551581b61 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 2 Dec 2022 09:42:51 +0100 Subject: [PATCH 35/60] Update --- .../ActionJustTextV1Deserializer.cs | 25 ++++++++ .../ActionMappers/ActionJustTextV1Mapper.cs | 59 ++++++++++++++++++ .../Actions/RepositoryActionJustTextV1.cs | 6 ++ .../Executors/BrowseActionExecutor.cs | 2 + .../Executors/DelegateActionExecutor.cs | 2 + .../Executors/NullActionExecutor.cs | 4 +- src/RepoM.App/MainWindow.xaml.cs | 10 ++- ...RecordStatisticsActionExecutorDecorator.cs | 7 ++- ...amicRepositoryActionDeserializerFactory.cs | 1 + .../Action/JustTextV1Test.cs | 61 +++++++++++++++++++ ...V1Test.Deserialize_JustText1.testfile.json | 30 +++++++++ ...tV1Test.Deserialize_JustText1.verified.txt | 36 +++++++++++ .../ActionMapperCompositionFactory.cs | 1 + 13 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionDeserializers/ActionJustTextV1Deserializer.cs create mode 100644 src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionJustTextV1Mapper.cs create mode 100644 src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/Data/Actions/RepositoryActionJustTextV1.cs create mode 100644 tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/JustTextV1Test.cs create mode 100644 tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/TestFiles/JustTextV1Test.Deserialize_JustText1.testfile.json create mode 100644 tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/Verified/JustTextV1Test.Deserialize_JustText1.verified.txt diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionDeserializers/ActionJustTextV1Deserializer.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionDeserializers/ActionJustTextV1Deserializer.cs new file mode 100644 index 00000000..a1ba9670 --- /dev/null +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionDeserializers/ActionJustTextV1Deserializer.cs @@ -0,0 +1,25 @@ +namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionDeserializers; + +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data; +using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; + +public class ActionJustTextV1Deserializer : IActionDeserializer +{ + bool IActionDeserializer.CanDeserialize(string type) + { + return "just-text@1".Equals(type, StringComparison.CurrentCultureIgnoreCase); + } + + RepositoryAction? IActionDeserializer.Deserialize(JToken jToken, ActionDeserializerComposition actionDeserializer, JsonSerializer jsonSerializer) + { + return Deserialize(jToken, jsonSerializer); + } + + private static RepositoryActionJustTextV1? Deserialize(JToken jToken, JsonSerializer jsonSerializer) + { + return jToken.ToObject(jsonSerializer); + } +} \ No newline at end of file diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionJustTextV1Mapper.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionJustTextV1Mapper.cs new file mode 100644 index 00000000..80a419b5 --- /dev/null +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/ActionMappers/ActionJustTextV1Mapper.cs @@ -0,0 +1,59 @@ +namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; + +using System; +using System.Collections.Generic; +using System.Linq; +using RepoM.Api.Common; +using RepoM.Api.Git; +using RepoM.Api.IO.ExpressionEvaluator; +using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Core.Plugin.RepositoryActions.Actions; +using RepositoryAction = RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.RepositoryAction; + +public class ActionJustTextV1Mapper : IActionToRepositoryActionMapper +{ + private readonly RepositoryExpressionEvaluator _expressionEvaluator; + private readonly ITranslationService _translationService; + + public ActionJustTextV1Mapper(RepositoryExpressionEvaluator expressionEvaluator, ITranslationService translationService) + { + _expressionEvaluator = expressionEvaluator ?? throw new ArgumentNullException(nameof(expressionEvaluator)); + _translationService = translationService ?? throw new ArgumentNullException(nameof(translationService)); + } + + bool IActionToRepositoryActionMapper.CanMap(RepositoryAction action) + { + return action is RepositoryActionJustTextV1; + } + + public bool CanHandleMultipleRepositories() + { + return false; + } + + IEnumerable IActionToRepositoryActionMapper.Map(RepositoryAction action, IEnumerable repository, ActionMapperComposition actionMapperComposition) + { + return Map(action as RepositoryActionJustTextV1, repository.First()); + } + + private IEnumerable Map(RepositoryActionJustTextV1? action, Repository repository) + { + if (action == null) + { + yield break; + } + + if (!_expressionEvaluator.EvaluateBooleanExpression(action.Active, repository)) + { + yield break; + } + + var name = NameHelper.EvaluateName(action.Name, repository, _translationService, _expressionEvaluator); + + yield return new Git.RepositoryAction(name, repository) + { + Action = NullAction.Instance, + CanExecute = _expressionEvaluator.EvaluateBooleanExpression(action.Enabled, repository), + }; + } +} \ No newline at end of file diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/Data/Actions/RepositoryActionJustTextV1.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/Data/Actions/RepositoryActionJustTextV1.cs new file mode 100644 index 00000000..68f37a78 --- /dev/null +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/Data/Actions/RepositoryActionJustTextV1.cs @@ -0,0 +1,6 @@ +namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; + +public class RepositoryActionJustTextV1 : RepositoryAction +{ + public string? Enabled { get; set; } +} \ No newline at end of file diff --git a/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs index 722d7ce1..f7a31326 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/BrowseActionExecutor.cs @@ -1,10 +1,12 @@ namespace RepoM.Api.RepositoryActions.Executors; using System; +using JetBrains.Annotations; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; +[UsedImplicitly] public class BrowseActionExecutor : IActionExecutor { public void Execute(IRepository repository, BrowseAction action) diff --git a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs index 52a66005..39537fd0 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/DelegateActionExecutor.cs @@ -1,9 +1,11 @@ namespace RepoM.Api.RepositoryActions.Executors; +using JetBrains.Annotations; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; +[UsedImplicitly] public class DelegateActionExecutor : IActionExecutor { public void Execute(IRepository repository, DelegateAction action) diff --git a/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs index 937eebff..0e4c39f8 100644 --- a/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs +++ b/src/RepoM.Api/RepositoryActions/Executors/NullActionExecutor.cs @@ -1,13 +1,15 @@ namespace RepoM.Api.RepositoryActions.Executors; +using JetBrains.Annotations; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; using RepoM.Core.Plugin.RepositoryActions.Actions; +[UsedImplicitly] public class NullActionExecutor : IActionExecutor { public void Execute(IRepository repository, NullAction action) { - return; + // intentionally do nothing. } } \ No newline at end of file diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index 3e268ec5..a74fb0cc 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -21,6 +21,7 @@ namespace RepoM.App; using RepoM.App.RepositoryActions; using RepoM.App.RepositoryOrdering; using RepoM.App.Services; +using RepoM.Core.Plugin.RepositoryActions.Actions; using RepoM.Core.Plugin.RepositoryOrdering; using SourceChord.FluentWPF; @@ -408,7 +409,7 @@ private void ShowUpdateIfAvailable() Action clickAction = (object clickSender, object clickArgs) => { - if (repositoryAction?.Action == null) + if (repositoryAction?.Action == null || repositoryAction.Action is NullAction) { return; } @@ -419,15 +420,12 @@ private void ShowUpdateIfAvailable() if (repositoryAction.ExecutionCausesSynchronizing) { Task.Run(() => SetViewsSynchronizing(affectedViews, true)) - .ContinueWith(t => - _executor.Execute(action.Repository, action.Action)) //repositoryAction.Action(null, coords)) - // .ContinueWith(t => DelegateActionExecutor.Instance.Execute(repositoryAction.Repository, da)) //repositoryAction.Action(null, coords)) + .ContinueWith(t => _executor.Execute(action.Repository, action.Action)) .ContinueWith(t => SetViewsSynchronizing(affectedViews, false)); } else { - Task.Run(() => - _executor.Execute(action.Repository, action.Action)); + Task.Run(() => _executor.Execute(action.Repository, action.Action)); } }; diff --git a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs index 835c3590..ec3bbaaa 100644 --- a/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs +++ b/src/RepoM.Plugin.Statistics/RepositoryActions/RecordStatisticsActionExecutorDecorator.cs @@ -4,6 +4,7 @@ namespace RepoM.Plugin.Statistics.RepositoryActions; using JetBrains.Annotations; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.RepositoryActions.Actions; [UsedImplicitly] public sealed class RecordStatisticsActionExecutorDecorator : IActionExecutor where T : IAction @@ -21,7 +22,11 @@ public RecordStatisticsActionExecutorDecorator( public void Execute(IRepository repository, T action) { - Record(repository); + if (action.GetType() != typeof(NullAction)) + { + Record(repository); + } + _decoratee.Execute(repository, action); } diff --git a/tests/RepoM.Api.Tests/DynamicRepositoryActionDeserializerFactory.cs b/tests/RepoM.Api.Tests/DynamicRepositoryActionDeserializerFactory.cs index 04f45043..2f13da13 100644 --- a/tests/RepoM.Api.Tests/DynamicRepositoryActionDeserializerFactory.cs +++ b/tests/RepoM.Api.Tests/DynamicRepositoryActionDeserializerFactory.cs @@ -26,6 +26,7 @@ public static JsonDynamicRepositoryActionDeserializer Create() new ActionAssociateFileV1Deserializer(), new ActionPinRepositoryV1Deserializer(), new ActionForEachV1Deserializer(), + new ActionJustTextV1Deserializer(), })); } diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/JustTextV1Test.cs b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/JustTextV1Test.cs new file mode 100644 index 00000000..643fc152 --- /dev/null +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/JustTextV1Test.cs @@ -0,0 +1,61 @@ +namespace RepoM.Api.Tests.IO.ModuleBasedRepositoryActionProvider.Action; + +using System.Threading.Tasks; +using EasyTestFile; +using EasyTestFileXunit; +using FluentAssertions; +using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionDeserializers; +using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Data.Actions; +using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Deserialization; +using VerifyTests; +using VerifyXunit; +using Xunit; + +[UsesEasyTestFile] +[UsesVerify] +public class JustTextV1Test +{ + private readonly JsonDynamicRepositoryActionDeserializer _sut; + private readonly EasyTestFileSettings _testFileSettings; + private readonly VerifySettings _verifySettings; + + public JustTextV1Test() + { + _sut = DynamicRepositoryActionDeserializerFactory.CreateWithDeserializer(new ActionJustTextV1Deserializer()); + + _testFileSettings = new EasyTestFileSettings(); + _testFileSettings.UseDirectory("TestFiles"); + _testFileSettings.UseExtension("json"); + + _verifySettings = new VerifySettings(); + _verifySettings.UseDirectory("Verified"); + } + + [Fact] + public async Task Deserialize_JustText1() + { + // arrange + var content = await EasyTestFile.LoadAsText(_testFileSettings); + + // act + var result = _sut.Deserialize(content); + + // assert + await Verifier.Verify(result, _verifySettings); + } + + + [Fact] + public async Task Deserialize_ShouldBeOfExpectedType() + { + // arrange + _testFileSettings.UseMethodName(nameof(Deserialize_JustText1)); + var content = await EasyTestFile.LoadAsText(_testFileSettings); + + // act + var result = _sut.Deserialize(content); + + // assert + _ = result.ActionsCollection.Actions.Should().AllBeOfType(); + } +} \ No newline at end of file diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/TestFiles/JustTextV1Test.Deserialize_JustText1.testfile.json b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/TestFiles/JustTextV1Test.Deserialize_JustText1.testfile.json new file mode 100644 index 00000000..8788cf19 --- /dev/null +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/TestFiles/JustTextV1Test.Deserialize_JustText1.testfile.json @@ -0,0 +1,30 @@ +{ + "repository-actions": { + "actions": [ + { + "type": "just-text@1", + "name": "This is a message" + }, + { + "type": "just-text@1", + "name": "This is a message 2", + "enabled": true + }, + { + "type": "just-text@1", + "name": "This is a message 3", + "enabled": false + }, + { + "type": "just-text@1", + "name": "This is a message 4", + "enabled": "false" + }, + { + "type": "just-text@1", + "name": "This is a message 5", + "enabled": "dummy" + } + ] + } +} \ No newline at end of file diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/Verified/JustTextV1Test.Deserialize_JustText1.verified.txt b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/Verified/JustTextV1Test.Deserialize_JustText1.verified.txt new file mode 100644 index 00000000..3d41364f --- /dev/null +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/Action/Verified/JustTextV1Test.Deserialize_JustText1.verified.txt @@ -0,0 +1,36 @@ +{ + TagsCollection: {}, + ActionsCollection: { + Actions: [ + { + $type: RepositoryActionJustTextV1, + Type: just-text@1, + Name: This is a message + }, + { + $type: RepositoryActionJustTextV1, + Enabled: true, + Type: just-text@1, + Name: This is a message 2 + }, + { + $type: RepositoryActionJustTextV1, + Enabled: false, + Type: just-text@1, + Name: This is a message 3 + }, + { + $type: RepositoryActionJustTextV1, + Enabled: false, + Type: just-text@1, + Name: This is a message 4 + }, + { + $type: RepositoryActionJustTextV1, + Enabled: dummy, + Type: just-text@1, + Name: This is a message 5 + } + ] + } +} \ No newline at end of file diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/ActionMapperCompositionFactory.cs b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/ActionMapperCompositionFactory.cs index 7ed1fb1c..89712ae0 100644 --- a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/ActionMapperCompositionFactory.cs +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/ActionMapperCompositionFactory.cs @@ -32,6 +32,7 @@ public static ActionMapperComposition Create( new ActionIgnoreRepositoriesV1Mapper(expressionEvaluator, translationService, repositoryMonitor), new ActionSeparatorV1Mapper(expressionEvaluator), new ActionAssociateFileV1Mapper(expressionEvaluator, translationService), + new ActionJustTextV1Mapper(expressionEvaluator, translationService), }; return new ActionMapperComposition(list, expressionEvaluator); From 93658ee7ecde524b47872f3a5a4a427ebaa38c71 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 20:30:22 +0100 Subject: [PATCH 36/60] wip --- .../Common/FileAppSettingsService.cs | 2 +- .../Git/DefaultRepositoryIgnoreStore.cs | 2 +- src/RepoM.Api/Git/DefaultRepositoryStore.cs | 2 +- .../IO/DefaultAppDataPathProvider.cs | 1 + .../RepositorySpecificConfiguration.cs | 1 + .../IO/Variables/EnvironmentVariableStore.cs | 1 - src/RepoM.App/MainWindow.xaml.cs | 3 +- src/RepoM.App/ViewModels/MenuItemViewModel.cs | 1 - .../Common}/IAppDataPathProvider.cs | 2 +- .../Interface/IEvent.cs | 10 ++ .../RepositoryActionRecordedEvent.cs | 10 ++ .../Ordering/LastOpenedComparer.cs | 66 +++++++++++ .../Ordering/LastOpenedComparerFactory.cs | 19 ++++ .../Ordering/LastOpenedConfigurationV1.cs | 12 ++ .../LastOpenedConfigurationV1Registration.cs | 13 +++ .../RepoM.Plugin.Statistics.csproj | 3 + .../RepositoryStatistics.cs | 50 +++++++++ .../StatisticsModule.cs | 106 +++++++++++++++++- .../StatisticsPackage.cs | 3 + .../StatisticsService.cs | 35 ++++-- .../IO/DefaultRepositoryActionProviderTest.cs | 2 +- .../RepositorySpecificConfigurationTest.cs | 2 +- .../Git/DefaultRepositoryIgnoreStoreTests.cs | 2 +- 23 files changed, 325 insertions(+), 23 deletions(-) rename src/{RepoM.Api/IO => RepoM.Core.Plugin/Common}/IAppDataPathProvider.cs (81%) create mode 100644 src/RepoM.Plugin.Statistics/Interface/IEvent.cs create mode 100644 src/RepoM.Plugin.Statistics/Interface/RepositoryActionRecordedEvent.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparer.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparerFactory.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1Registration.cs create mode 100644 src/RepoM.Plugin.Statistics/RepositoryStatistics.cs diff --git a/src/RepoM.Api/Common/FileAppSettingsService.cs b/src/RepoM.Api/Common/FileAppSettingsService.cs index 3367f803..74f49b95 100644 --- a/src/RepoM.Api/Common/FileAppSettingsService.cs +++ b/src/RepoM.Api/Common/FileAppSettingsService.cs @@ -7,7 +7,7 @@ namespace RepoM.Api.Common; using System.Linq; using Newtonsoft.Json; using RepoM.Api.Git.AutoFetch; -using RepoM.Api.IO; +using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; diff --git a/src/RepoM.Api/Git/DefaultRepositoryIgnoreStore.cs b/src/RepoM.Api/Git/DefaultRepositoryIgnoreStore.cs index 303659cb..13fbda7f 100644 --- a/src/RepoM.Api/Git/DefaultRepositoryIgnoreStore.cs +++ b/src/RepoM.Api/Git/DefaultRepositoryIgnoreStore.cs @@ -5,7 +5,7 @@ namespace RepoM.Api.Git; using System.IO; using System.IO.Abstractions; using System.Linq; -using RepoM.Api.IO; +using RepoM.Core.Plugin.Common; public class DefaultRepositoryIgnoreStore : FileRepositoryStore, IRepositoryIgnoreStore { diff --git a/src/RepoM.Api/Git/DefaultRepositoryStore.cs b/src/RepoM.Api/Git/DefaultRepositoryStore.cs index 3ae39a8f..e6364569 100644 --- a/src/RepoM.Api/Git/DefaultRepositoryStore.cs +++ b/src/RepoM.Api/Git/DefaultRepositoryStore.cs @@ -3,7 +3,7 @@ namespace RepoM.Api.Git; using System; using System.IO; using System.IO.Abstractions; -using RepoM.Api.IO; +using RepoM.Core.Plugin.Common; public class DefaultRepositoryStore : FileRepositoryStore { diff --git a/src/RepoM.Api/IO/DefaultAppDataPathProvider.cs b/src/RepoM.Api/IO/DefaultAppDataPathProvider.cs index 62c5884e..f6070c97 100644 --- a/src/RepoM.Api/IO/DefaultAppDataPathProvider.cs +++ b/src/RepoM.Api/IO/DefaultAppDataPathProvider.cs @@ -2,6 +2,7 @@ namespace RepoM.Api.IO; using System; using System.IO; +using RepoM.Core.Plugin.Common; public class DefaultAppDataPathProvider : IAppDataPathProvider { diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs index d69db6e1..10374b3d 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs @@ -16,6 +16,7 @@ namespace RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Deserialization; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Exceptions; using RepoM.Api.IO.Variables; +using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.RepositoryActions.Actions; using IRepository = RepoM.Core.Plugin.Repository.IRepository; using Repository = RepoM.Api.Git.Repository; diff --git a/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs b/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs index 79e7c934..b236be2d 100644 --- a/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs +++ b/src/RepoM.Api/IO/Variables/EnvironmentVariableStore.cs @@ -3,7 +3,6 @@ namespace RepoM.Api.IO.Variables; using System; using System.Collections.Generic; using System.Threading; -using RepoM.Api.Git; using RepoM.Core.Plugin.Repository; public static class EnvironmentVariableStore diff --git a/src/RepoM.App/MainWindow.xaml.cs b/src/RepoM.App/MainWindow.xaml.cs index a74fb0cc..416aacd7 100644 --- a/src/RepoM.App/MainWindow.xaml.cs +++ b/src/RepoM.App/MainWindow.xaml.cs @@ -16,13 +16,12 @@ namespace RepoM.App; using RepoM.Api; using RepoM.Api.Common; using RepoM.Api.Git; -using RepoM.Api.IO; using RepoM.App.Controls; using RepoM.App.RepositoryActions; using RepoM.App.RepositoryOrdering; using RepoM.App.Services; +using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.RepositoryActions.Actions; -using RepoM.Core.Plugin.RepositoryOrdering; using SourceChord.FluentWPF; /// diff --git a/src/RepoM.App/ViewModels/MenuItemViewModel.cs b/src/RepoM.App/ViewModels/MenuItemViewModel.cs index e7c9c563..8700cad4 100644 --- a/src/RepoM.App/ViewModels/MenuItemViewModel.cs +++ b/src/RepoM.App/ViewModels/MenuItemViewModel.cs @@ -3,7 +3,6 @@ namespace RepoM.App.ViewModels; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; -using System.Windows.Input; // https://stackoverflow.com/questions/5912687/styling-contextmenu-and-contextmenu-items // https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/contextmenu-styles-and-templates?view=netframeworkdesktop-4.8 diff --git a/src/RepoM.Api/IO/IAppDataPathProvider.cs b/src/RepoM.Core.Plugin/Common/IAppDataPathProvider.cs similarity index 81% rename from src/RepoM.Api/IO/IAppDataPathProvider.cs rename to src/RepoM.Core.Plugin/Common/IAppDataPathProvider.cs index eb2df89d..7e79e77a 100644 --- a/src/RepoM.Api/IO/IAppDataPathProvider.cs +++ b/src/RepoM.Core.Plugin/Common/IAppDataPathProvider.cs @@ -1,4 +1,4 @@ -namespace RepoM.Api.IO; +namespace RepoM.Core.Plugin.Common; using System; diff --git a/src/RepoM.Plugin.Statistics/Interface/IEvent.cs b/src/RepoM.Plugin.Statistics/Interface/IEvent.cs new file mode 100644 index 00000000..9ece58c3 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Interface/IEvent.cs @@ -0,0 +1,10 @@ +namespace RepoM.Plugin.Statistics.Interface; + +using System; + +public interface IEvent +{ + public string Repository { get; set; } + + public DateTime Timestamp { get; set; } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Interface/RepositoryActionRecordedEvent.cs b/src/RepoM.Plugin.Statistics/Interface/RepositoryActionRecordedEvent.cs new file mode 100644 index 00000000..c180c96c --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Interface/RepositoryActionRecordedEvent.cs @@ -0,0 +1,10 @@ +namespace RepoM.Plugin.Statistics.Interface; + +using System; + +internal class RepositoryActionRecordedEvent : IEvent +{ + public string Repository { get; set; } = null!; + + public DateTime Timestamp { get; set; } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparer.cs b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparer.cs new file mode 100644 index 00000000..cd5d9dde --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparer.cs @@ -0,0 +1,66 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System; +using System.Collections.Generic; +using System.Linq; +using RepoM.Core.Plugin.Repository; +using RepoM.Core.Plugin.RepositoryOrdering; + +internal class LastOpenedComparer : IRepositoryComparer +{ + private readonly StatisticsService _service; + private readonly int _weight; + + public LastOpenedComparer(StatisticsService service, int weight) + { + _service = service ?? throw new ArgumentNullException(nameof(service)); + _weight = weight; + } + + public int Compare(IRepository? x, IRepository? y) + { + if (_weight == 0) + { + return 0; + } + + if (ReferenceEquals(x, y)) + { + return 0; + } + + if (ReferenceEquals(null, y)) + { + return _weight; + } + + if (ReferenceEquals(null, x)) + { + return -1 * _weight; + } + + DateTime lastX = GetLast(x); + DateTime lastY = GetLast(y); + + if (lastX == lastY) + { + return 0; + } + + if (lastX < lastY) + { + return _weight; + } + + return -1 * _weight; + } + + private DateTime GetLast(IRepository repository) + { + IReadOnlyList items = _service.GetRecordings(repository); + + return items.Count == 0 + ? DateTime.MinValue + : items.MaxBy(x => x); + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparerFactory.cs new file mode 100644 index 00000000..fa4d63b0 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedComparerFactory.cs @@ -0,0 +1,19 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System; +using RepoM.Core.Plugin.RepositoryOrdering; + +public sealed class LastOpenedComparerFactory : IRepositoryComparerFactory +{ + private readonly StatisticsService _service; + + public LastOpenedComparerFactory(StatisticsService service) + { + _service = service ?? throw new ArgumentNullException(nameof(service)); + } + + public IRepositoryComparer Create(LastOpenedConfigurationV1 configuration) + { + return new LastOpenedComparer(_service, configuration.Weight); + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs new file mode 100644 index 00000000..f966dfc7 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs @@ -0,0 +1,12 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +public sealed class LastOpenedConfigurationV1 : IRepositoriesComparerConfiguration +{ + public LastOpenedConfigurationV1() + { + } + + public int Weight { get; set; } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1Registration.cs b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1Registration.cs new file mode 100644 index 00000000..9197ab09 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1Registration.cs @@ -0,0 +1,13 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System; +using JetBrains.Annotations; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +[UsedImplicitly] +public class LastOpenedConfigurationV1Registration : IConfigurationRegistration +{ + public Type ConfigurationType { get; } = typeof(LastOpenedConfigurationV1); + + public string Tag => "last-opened-comparer@1"; +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj index 474a0eed..e4aa1a55 100644 --- a/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj +++ b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj @@ -6,8 +6,11 @@ + + + diff --git a/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs b/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs new file mode 100644 index 00000000..5e2b59c1 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs @@ -0,0 +1,50 @@ +namespace RepoM.Plugin.Statistics; + +using System; +using System.Collections.Generic; +using RepoM.Core.Plugin.Common; +using RepoM.Plugin.Statistics.Interface; + +internal class RepositoryStatistics +{ + private readonly IClock _clock; + + public RepositoryStatistics(string repositoryPath, IClock clock) + { + RepositoryPath = repositoryPath ?? throw new ArgumentNullException(nameof(repositoryPath)); + _clock = clock ?? throw new ArgumentNullException(nameof(clock)); + } + + public string RepositoryPath { get; } + + public List Recordings { get; } = new(); + + public IEvent Record() + { + var evt = new RepositoryActionRecordedEvent + { + Repository = RepositoryPath, + Timestamp = _clock.Now, + }; + + Apply(evt); + + return evt; + } + + public void Apply(IEvent evt) + { + if (evt is RepositoryActionRecordedEvent repositoryActionRecordedEvent) + { + Apply(repositoryActionRecordedEvent); + return; + } + + throw new NotImplementedException(); + } + + private void Apply(RepositoryActionRecordedEvent evt) + { + Recordings.Add(evt.Timestamp); + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsModule.cs b/src/RepoM.Plugin.Statistics/StatisticsModule.cs index 01492555..7f958f10 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsModule.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsModule.cs @@ -1,28 +1,126 @@ namespace RepoM.Plugin.Statistics; using System; +using System.IO; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; using RepoM.Core.Plugin; +using RepoM.Core.Plugin.Common; +using RepoM.Plugin.Statistics.Interface; [UsedImplicitly] internal class StatisticsModule : IModule { private readonly StatisticsService _service; + private readonly IClock _clock; + private readonly IAppDataPathProvider _pathProvider; + private readonly ILogger _logger; + private string _basePath = string.Empty; + private IDisposable? _disposable; + private readonly JsonSerializerSettings _settings; - public StatisticsModule(StatisticsService service) + public StatisticsModule(StatisticsService service, IClock clock, IAppDataPathProvider pathProvider, ILogger logger) { _service = service ?? throw new ArgumentNullException(nameof(service)); + _clock = clock ?? throw new ArgumentNullException(nameof(clock)); + _pathProvider = pathProvider ?? throw new ArgumentNullException(nameof(pathProvider)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + + _settings = new JsonSerializerSettings + { + Formatting = Formatting.None, + NullValueHandling = NullValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.All, + }; } - public Task StartAsync() + public async Task StartAsync() { - return Task.CompletedTask; - // return _service.InitializeAsync(); + _basePath = Path.Combine(_pathProvider.GetAppDataPath(), "Module", "Statistics"); + + _disposable = WriteEventsToFile(); + + await ProcessEventsFromFile().ConfigureAwait(false); + } + + private async Task ProcessEventsFromFile() + { + IOrderedEnumerable orderedEnumerable = Directory.GetFiles(_basePath, "statistics.v1.*.json").OrderBy(f => f); + + foreach (var file in orderedEnumerable) + { + IEvent[] list = Array.Empty(); + + try + { + var json = await File.ReadAllTextAsync(file, CancellationToken.None).ConfigureAwait(false); + list = JsonConvert.DeserializeObject(json, _settings) ?? Array.Empty(); + } + catch (Exception e) + { + _logger.LogError(e, "Could not read or deserialize data from '{filename}'. {message}", file, e.Message); + } + + foreach (IEvent item in list) + { + _service.Apply(item); + } + } + } + + private IDisposable WriteEventsToFile() + { + return _service + .Events + .ObserveOn(Scheduler.Default) + .Buffer(TimeSpan.FromMinutes(5)) + .Subscribe(data => + { + IEvent[] events = data.ToArray(); + if (events.Length == 0) + { + return; + } + + var json = JsonConvert.SerializeObject(events, _settings); + var filename = Path.Combine(_basePath, $"statistics.v1.{_clock.Now:yyyy-MM-dd HH.mm.ss}.json"); + + if (!Directory.Exists(_basePath)) + { + try + { + _logger.LogDebug("Try Create directory '{basePath}'.", _basePath); + Directory.CreateDirectory(_basePath); + } + catch (Exception e) + { + _logger.LogError(e, "Could not create directory '{basePath}'. {message}", _basePath, e.Message); + } + } + + if (Directory.Exists(_basePath)) + { + try + { + File.WriteAllText(filename, json); + } + catch (Exception e) + { + _logger.LogError(e, "Could not write json to '{filename}'. {message}", filename, e.Message); + } + } + }); } public Task StopAsync() { + _disposable?.Dispose(); return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs index ddcb6170..26ec41f0 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsPackage.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsPackage.cs @@ -27,6 +27,9 @@ private static void RegisterPluginHooks(Container container) container.Collection.Append(Lifestyle.Singleton); container.Register, UsageScorerFactory>(Lifestyle.Singleton); + container.Collection.Append(Lifestyle.Singleton); + container.Register, LastOpenedComparerFactory>(Lifestyle.Singleton); + // action executor container.RegisterDecorator(typeof(IActionExecutor<>), typeof(RecordStatisticsActionExecutorDecorator<>), Lifestyle.Singleton); diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs index 4f14ee48..4aca9b15 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsService.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -1,40 +1,59 @@ namespace RepoM.Plugin.Statistics; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Reactive.Subjects; using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.Repository; +using RepoM.Plugin.Statistics.Interface; public class StatisticsService { private readonly IClock _clock; private readonly ReadOnlyCollection _empty = new List(0).AsReadOnly(); - private readonly Dictionary> _recordings = new(); + private readonly ConcurrentDictionary _recordings = new(); + private readonly Subject _events; public StatisticsService(IClock clock) { _clock = clock ?? throw new ArgumentNullException(nameof(clock)); + _events = new Subject(); } + public IObservable Events => _events; + public void Record(IRepository repository) { - if (!_recordings.TryGetValue(repository.SafePath, out List? list)) + if (!_recordings.TryGetValue(repository.SafePath, out RepositoryStatistics? repositoryStatistics)) { - list = new List(); - _recordings.TryAdd(repository.SafePath, list); + repositoryStatistics = new RepositoryStatistics(repository.SafePath, _clock); + _recordings.TryAdd(repository.SafePath, repositoryStatistics); } - list.Add(_clock.Now); + IEvent evt = repositoryStatistics.Record(); + _events.OnNext(evt); } public IReadOnlyList GetRecordings(IRepository repository) { - if (_recordings.TryGetValue(repository.SafePath, out List? list)) + if (_recordings.TryGetValue(repository.SafePath, out RepositoryStatistics? repositoryStatistics)) { - return list.AsReadOnly(); + return repositoryStatistics.Recordings.AsReadOnly(); } return _empty; - } + } + + public void Apply(IEvent evt) + { + if (!_recordings.TryGetValue(evt.Repository, out RepositoryStatistics? repositoryStatistics)) + { + repositoryStatistics = new RepositoryStatistics(evt.Repository, _clock); + _recordings.TryAdd(evt.Repository, repositoryStatistics); + } + + repositoryStatistics.Apply(evt); + } } \ No newline at end of file diff --git a/tests/RepoM.Api.Tests/IO/DefaultRepositoryActionProviderTest.cs b/tests/RepoM.Api.Tests/IO/DefaultRepositoryActionProviderTest.cs index 68265d9d..b1963b2b 100644 --- a/tests/RepoM.Api.Tests/IO/DefaultRepositoryActionProviderTest.cs +++ b/tests/RepoM.Api.Tests/IO/DefaultRepositoryActionProviderTest.cs @@ -15,8 +15,8 @@ namespace RepoM.Api.Common.Tests.IO; using FakeItEasy; using RepoM.Api.Common; using RepoM.Api.Git; -using RepoM.Api.IO; using RepoM.Api.IO.VariableProviders; +using RepoM.Core.Plugin.Common; using VerifyXunit; [UsesEasyTestFile] diff --git a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs index 76aa27c3..d9b4dc37 100644 --- a/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs +++ b/tests/RepoM.Api.Tests/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfigurationTest.cs @@ -21,12 +21,12 @@ namespace RepoM.Api.Tests.IO.ModuleBasedRepositoryActionProvider; using Microsoft.Extensions.Logging.Abstractions; using RepoM.Api.Common; using RepoM.Api.Git; -using RepoM.Api.IO; using RepoM.Api.IO.ExpressionEvaluator; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.ActionMappers; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider.Deserialization; using RepoM.Api.IO.VariableProviders; +using RepoM.Core.Plugin.Common; using VerifyTests; using VerifyXunit; using Xunit; diff --git a/tests/Tests/Git/DefaultRepositoryIgnoreStoreTests.cs b/tests/Tests/Git/DefaultRepositoryIgnoreStoreTests.cs index 43944df0..76a055fc 100644 --- a/tests/Tests/Git/DefaultRepositoryIgnoreStoreTests.cs +++ b/tests/Tests/Git/DefaultRepositoryIgnoreStoreTests.cs @@ -5,7 +5,7 @@ namespace Tests.Git; using Moq; using NUnit.Framework; using RepoM.Api.Git; -using RepoM.Api.IO; +using RepoM.Core.Plugin.Common; public class DefaultRepositoryIgnoreStoreTests { From 193d260fb02d44a624bc30906dcd4959782ac3a6 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 20:47:49 +0100 Subject: [PATCH 37/60] Adding tests --- RepoM.sln | 23 +++++++++ .../UsageVariableProvider.cs | 2 +- .../RepoM.Plugin.AzureDevOps.Tests.csproj | 1 - .../RepoM.Plugin.LuceneSearch.Tests.csproj | 1 - .../RepoM.Plugin.SonarCloud.Tests.csproj | 1 - .../RepoM.Plugin.Statistics.Tests.csproj | 37 ++++++++++++++ .../StatisticsPackageTest.cs | 48 +++++++++++++++++++ .../TestFramework/VerifierInitializer.cs | 15 ++++++ 8 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj create mode 100644 tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs create mode 100644 tests/RepoM.Plugin.Statistics.Tests/TestFramework/VerifierInitializer.cs diff --git a/RepoM.sln b/RepoM.sln index 1d707d56..2f1361ec 100644 --- a/RepoM.sln +++ b/RepoM.sln @@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yaml.Poc.Tests", "tests\Yam EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.Statistics", "src\RepoM.Plugin.Statistics\RepoM.Plugin.Statistics.csproj", "{DF4F5FA8-0E3F-4D84-A048-20242FD032BC}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.Statistics.Tests", "tests\RepoM.Plugin.Statistics.Tests\RepoM.Plugin.Statistics.Tests.csproj", "{C90AA844-B355-4C62-96FA-D4F338EE094A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -371,6 +373,26 @@ Global {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|x64.Build.0 = Release|Any CPU {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|x86.ActiveCfg = Release|Any CPU {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Release|x86.Build.0 = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|ARM.Build.0 = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|ARM64.Build.0 = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|x64.ActiveCfg = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|x64.Build.0 = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|x86.ActiveCfg = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Debug|x86.Build.0 = Debug|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|Any CPU.Build.0 = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|ARM.ActiveCfg = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|ARM.Build.0 = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|ARM64.ActiveCfg = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|ARM64.Build.0 = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|x64.ActiveCfg = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|x64.Build.0 = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|x86.ActiveCfg = Release|Any CPU + {C90AA844-B355-4C62-96FA-D4F338EE094A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -385,6 +407,7 @@ Global {26FF9590-66C7-4B87-9574-E816E1E36628} = {D6E372DC-10D3-4997-9DFC-568B4666635A} {C2014EE2-F17C-478E-B282-9D0971065BB8} = {D6E372DC-10D3-4997-9DFC-568B4666635A} {DF4F5FA8-0E3F-4D84-A048-20242FD032BC} = {D6E372DC-10D3-4997-9DFC-568B4666635A} + {C90AA844-B355-4C62-96FA-D4F338EE094A} = {D6E372DC-10D3-4997-9DFC-568B4666635A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1765ABAA-0652-4DA5-ABBF-05396F2957D7} diff --git a/src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs b/src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs index 6cf6f0eb..c9703524 100644 --- a/src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs +++ b/src/RepoM.Plugin.Statistics/VariableProviders/UsageVariableProvider.cs @@ -18,7 +18,7 @@ public UsageVariableProvider(StatisticsService service) public bool CanProvide(string key) { - return !string.IsNullOrWhiteSpace(key) && key.StartsWith("usage", StringComparison.CurrentCultureIgnoreCase); + return !string.IsNullOrWhiteSpace(key) && key.Equals("usage", StringComparison.CurrentCultureIgnoreCase); } public object? Provide(RepositoryContext context, string key, string? arg) diff --git a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj index 43524013..e45bc1a3 100644 --- a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj +++ b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj @@ -2,7 +2,6 @@ net6.0 - false diff --git a/tests/RepoM.Plugin.LuceneSearch.Tests/RepoM.Plugin.LuceneSearch.Tests.csproj b/tests/RepoM.Plugin.LuceneSearch.Tests/RepoM.Plugin.LuceneSearch.Tests.csproj index 90fef40c..b99d2c58 100644 --- a/tests/RepoM.Plugin.LuceneSearch.Tests/RepoM.Plugin.LuceneSearch.Tests.csproj +++ b/tests/RepoM.Plugin.LuceneSearch.Tests/RepoM.Plugin.LuceneSearch.Tests.csproj @@ -2,7 +2,6 @@ net6.0 - false diff --git a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj index 99b4343e..cf0b7d2c 100644 --- a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj +++ b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj @@ -2,7 +2,6 @@ net6.0 - false diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj new file mode 100644 index 00000000..12615565 --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj @@ -0,0 +1,37 @@ + + + + net6.0 + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs b/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs new file mode 100644 index 00000000..14c58a87 --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs @@ -0,0 +1,48 @@ +namespace RepoM.Plugin.Statistics.Tests; + +using System; +using FakeItEasy; +using Microsoft.Extensions.Logging; +using RepoM.Core.Plugin.Common; +using SimpleInjector; +using Xunit; + +public class StatisticsPackageTest +{ + [Fact] + public void RegisterServices_ShouldBeSuccessful_WhenExternalDependenciesAreRegistered() + { + // arrange + var container = new Container(); + RegisterExternals(container); + var sut = new StatisticsPackage(); + + // act + sut.RegisterServices(container); + + // assert + // implicit, Verify throws when container is not valid. + container.Verify(VerificationOption.VerifyAndDiagnose); + } + + [Fact] + public void RegisterServices_ShouldFail_WhenExternalDependenciesAreNotRegistered() + { + // arrange + var container = new Container(); + var sut = new StatisticsPackage(); + + // act + sut.RegisterServices(container); + + // assert + Assert.Throws(() => container.Verify(VerificationOption.VerifyAndDiagnose)); + } + + private static void RegisterExternals(Container container) + { + container.RegisterSingleton(A.Dummy); + container.RegisterSingleton(A.Dummy); + container.RegisterSingleton(A.Dummy>); + } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/TestFramework/VerifierInitializer.cs b/tests/RepoM.Plugin.Statistics.Tests/TestFramework/VerifierInitializer.cs new file mode 100644 index 00000000..6ba48f5e --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/TestFramework/VerifierInitializer.cs @@ -0,0 +1,15 @@ +namespace RepoM.Plugin.Statistics.Tests.TestFramework; + +using System.Runtime.CompilerServices; +using Argon; +using VerifyTests; + +public static class VerifierInitializer +{ + [ModuleInitializer] + public static void Initialize() + { + VerifierSettings.DisableRequireUniquePrefix(); + VerifierSettings.AddExtraSettings(serializerSettings => serializerSettings.TypeNameHandling = TypeNameHandling.Auto); + } +} \ No newline at end of file From 1ac507f1b6abe75bae2a9f2917b97a05c06f0e4b Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 21:04:55 +0100 Subject: [PATCH 38/60] add tests --- .../DummyEvent.cs | 11 ++ ...Test.Record_ShouldReturnEvent.verified.txt | 4 + .../RepositoryStatisticsTest.cs | 119 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs create mode 100644 tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.Record_ShouldReturnEvent.verified.txt create mode 100644 tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs diff --git a/tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs b/tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs new file mode 100644 index 00000000..18ac45b7 --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs @@ -0,0 +1,11 @@ +namespace RepoM.Plugin.Statistics.Tests; + +using System; +using RepoM.Plugin.Statistics.Interface; + +internal class DummyEvent : IEvent +{ + public string Repository { get; set; } + + public DateTime Timestamp { get; set; } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.Record_ShouldReturnEvent.verified.txt b/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.Record_ShouldReturnEvent.verified.txt new file mode 100644 index 00000000..584ae99d --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.Record_ShouldReturnEvent.verified.txt @@ -0,0 +1,4 @@ +{ + Repository: path, + Timestamp: 2022-12-13 15:17:08 Local +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs b/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs new file mode 100644 index 00000000..c313578f --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs @@ -0,0 +1,119 @@ +namespace RepoM.Plugin.Statistics.Tests; + +using System; +using System.Threading.Tasks; +using FakeItEasy; +using FluentAssertions; +using RepoM.Core.Plugin.Common; +using RepoM.Plugin.Statistics.Interface; +using VerifyXunit; +using Xunit; + +[UsesVerify] +public class RepositoryStatisticsTest +{ + [Fact] + public void Recordings_ShouldBeEmpty_WhenConstructed() + { + // arrange + IClock clock = A.Fake(); + + // act + var sut = new RepositoryStatistics("path", clock); + + // assert + sut.Recordings.Should().BeEmpty(); + } + + [Fact] + public void Apply_ShouldAddTimestampToRecordings_WhenEventIsRepositoryActionRecordedEvent() + { + // arrange + DateTime now = DateTime.Now.AddMinutes(-1000); + IClock clock = A.Fake(); + var sut = new RepositoryStatistics("path", clock); + + // act + sut.Apply(new RepositoryActionRecordedEvent + { + Repository = "path", + Timestamp = now, + }); + + // assert + sut.Recordings.Should().BeEquivalentTo(new[] { now, }); + } + + [Fact] + public void Apply_ShouldAddTimestampToRecordings_WhenEventIsRepositoryActionRecordedEventWithAlreadyOneDateInside() + { + // arrange + DateTime now1 = DateTime.Now.AddMinutes(-1000); + DateTime now2 = DateTime.Now.AddMinutes(-100); + IClock clock = A.Fake(); + var sut = new RepositoryStatistics("path", clock); + sut.Apply(new RepositoryActionRecordedEvent + { + Repository = "path", + Timestamp = now1, + }); + + // act + sut.Apply(new RepositoryActionRecordedEvent + { + Repository = "path", + Timestamp = now2, + }); + + // assert + sut.Recordings.Should().BeEquivalentTo(new[] { now1, now2, }); + } + + [Fact] + public void Apply_ShouldThrow_WhenEventTypeIsWrong() + { + // arrange + IClock clock = A.Fake(); + var sut = new RepositoryStatistics("path", clock); + + // act + Action act = () => sut.Apply(new DummyEvent()); + + // assert + act.Should().Throw(); + } + + + [Fact] + public void Record_ShouldAddTimestampToRecording() + { + // arrange + DateTime now = DateTime.Now.AddMinutes(-1000); + IClock clock = A.Fake(); + A.CallTo(() => clock.Now).Returns(now); + var sut = new RepositoryStatistics("path", clock); + + // act + _ = sut.Record(); + + // assert + sut.Recordings.Should().BeEquivalentTo(new[] { now, }); + } + + [Fact] + public async Task Record_ShouldReturnEvent() + { + // arrange + var now = new DateTime(2022, 12, 13, 15, 17, 8, DateTimeKind.Local); + IClock clock = A.Fake(); + A.CallTo(() => clock.Now).Returns(now); + var sut = new RepositoryStatistics("path", clock); + + // act + IEvent evt = sut.Record(); + + // assert + evt.Should().BeOfType(); + await Verifier.Verify(evt).DontScrubDateTimes(); + } +} \ No newline at end of file From 30f73b6502e9337c7fd3d4c5b55e16bfd72df7da Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 21:06:32 +0100 Subject: [PATCH 39/60] styling --- src/RepoM.Plugin.Statistics/RepositoryStatistics.cs | 9 ++++----- .../RepositoryStatisticsTest.cs | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs b/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs index 5e2b59c1..26e11a64 100644 --- a/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs +++ b/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs @@ -7,23 +7,22 @@ namespace RepoM.Plugin.Statistics; internal class RepositoryStatistics { + private readonly string _repositoryPath; private readonly IClock _clock; - + public RepositoryStatistics(string repositoryPath, IClock clock) { - RepositoryPath = repositoryPath ?? throw new ArgumentNullException(nameof(repositoryPath)); + _repositoryPath = repositoryPath ?? throw new ArgumentNullException(nameof(repositoryPath)); _clock = clock ?? throw new ArgumentNullException(nameof(clock)); } - public string RepositoryPath { get; } - public List Recordings { get; } = new(); public IEvent Record() { var evt = new RepositoryActionRecordedEvent { - Repository = RepositoryPath, + Repository = _repositoryPath, Timestamp = _clock.Now, }; diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs b/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs index c313578f..23df53b1 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/RepositoryStatisticsTest.cs @@ -82,8 +82,7 @@ public void Apply_ShouldThrow_WhenEventTypeIsWrong() // assert act.Should().Throw(); } - - + [Fact] public void Record_ShouldAddTimestampToRecording() { From 55c2cd8e9be93cfda6eeb0d3d7b4babe7a346630 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 21:17:17 +0100 Subject: [PATCH 40/60] Depend on System.IO.Abstractions in Statistics project --- .../RepositorySpecificConfiguration.cs | 9 ++++++- src/RepoM.Api/RepoM.Api.csproj | 2 +- src/RepoM.App/MainWindowPageModel.cs | 1 - src/RepoM.App/RepoM.App.csproj | 2 +- .../RepoM.Core.Plugin.csproj | 1 + .../StatisticsModule.cs | 27 ++++++++++++------- tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj | 4 +-- .../RepoM.Plugin.AzureDevOps.Tests.csproj | 4 +-- .../RepoM.Plugin.SonarCloud.Tests.csproj | 4 +-- .../RepoM.Plugin.Statistics.Tests.csproj | 4 +-- .../StatisticsPackageTest.cs | 2 ++ tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj | 4 +-- 12 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs index 10374b3d..2fff680f 100644 --- a/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs +++ b/src/RepoM.Api/IO/ModuleBasedRepositoryActionProvider/RepositorySpecificConfiguration.cs @@ -528,7 +528,14 @@ private IEnumerable CreateFailing(Exception ex, string? filena { yield return new RepositoryAction(_translationService.Translate("Fix"), repository) { - Action = new DelegateAction((_, _) => ProcessHelper.StartProcess(_fileSystem.Path.GetDirectoryName(filename), string.Empty)), + Action = new DelegateAction((_, _) => + { + var directoryName = _fileSystem.Path.GetDirectoryName(filename); + if (directoryName != null) + { + ProcessHelper.StartProcess(directoryName, string.Empty); + } + }), }; } } diff --git a/src/RepoM.Api/RepoM.Api.csproj b/src/RepoM.Api/RepoM.Api.csproj index 32bcf80a..5531719f 100644 --- a/src/RepoM.Api/RepoM.Api.csproj +++ b/src/RepoM.Api/RepoM.Api.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/RepoM.App/MainWindowPageModel.cs b/src/RepoM.App/MainWindowPageModel.cs index 0516c19a..af380e20 100644 --- a/src/RepoM.App/MainWindowPageModel.cs +++ b/src/RepoM.App/MainWindowPageModel.cs @@ -9,7 +9,6 @@ namespace RepoM.App; using RepoM.App.RepositoryOrdering; using RepoM.App.ViewModels; - public class SortMenuItemViewModel : MenuItemViewModel { private readonly Func _isSelectedFunc; diff --git a/src/RepoM.App/RepoM.App.csproj b/src/RepoM.App/RepoM.App.csproj index 33ed14dc..bda3d056 100644 --- a/src/RepoM.App/RepoM.App.csproj +++ b/src/RepoM.App/RepoM.App.csproj @@ -44,7 +44,7 @@ - + diff --git a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj index 32163da6..ea4447da 100644 --- a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj +++ b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj @@ -6,6 +6,7 @@ + diff --git a/src/RepoM.Plugin.Statistics/StatisticsModule.cs b/src/RepoM.Plugin.Statistics/StatisticsModule.cs index 7f958f10..e93d47fc 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsModule.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsModule.cs @@ -1,7 +1,7 @@ namespace RepoM.Plugin.Statistics; using System; -using System.IO; +using System.IO.Abstractions; using System.Linq; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -20,16 +20,23 @@ internal class StatisticsModule : IModule private readonly StatisticsService _service; private readonly IClock _clock; private readonly IAppDataPathProvider _pathProvider; + private readonly IFileSystem _fileSystem; private readonly ILogger _logger; private string _basePath = string.Empty; private IDisposable? _disposable; private readonly JsonSerializerSettings _settings; - public StatisticsModule(StatisticsService service, IClock clock, IAppDataPathProvider pathProvider, ILogger logger) + public StatisticsModule( + StatisticsService service, + IClock clock, + IAppDataPathProvider pathProvider, + IFileSystem fileSystem, + ILogger logger) { _service = service ?? throw new ArgumentNullException(nameof(service)); _clock = clock ?? throw new ArgumentNullException(nameof(clock)); _pathProvider = pathProvider ?? throw new ArgumentNullException(nameof(pathProvider)); + _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _settings = new JsonSerializerSettings @@ -42,7 +49,7 @@ public StatisticsModule(StatisticsService service, IClock clock, IAppDataPathPro public async Task StartAsync() { - _basePath = Path.Combine(_pathProvider.GetAppDataPath(), "Module", "Statistics"); + _basePath = _fileSystem.Path.Combine(_pathProvider.GetAppDataPath(), "Module", "Statistics"); _disposable = WriteEventsToFile(); @@ -51,7 +58,7 @@ public async Task StartAsync() private async Task ProcessEventsFromFile() { - IOrderedEnumerable orderedEnumerable = Directory.GetFiles(_basePath, "statistics.v1.*.json").OrderBy(f => f); + IOrderedEnumerable orderedEnumerable = _fileSystem.Directory.GetFiles(_basePath, "statistics.v1.*.json").OrderBy(f => f); foreach (var file in orderedEnumerable) { @@ -59,7 +66,7 @@ private async Task ProcessEventsFromFile() try { - var json = await File.ReadAllTextAsync(file, CancellationToken.None).ConfigureAwait(false); + var json = await _fileSystem.File.ReadAllTextAsync(file, CancellationToken.None).ConfigureAwait(false); list = JsonConvert.DeserializeObject(json, _settings) ?? Array.Empty(); } catch (Exception e) @@ -89,14 +96,14 @@ private IDisposable WriteEventsToFile() } var json = JsonConvert.SerializeObject(events, _settings); - var filename = Path.Combine(_basePath, $"statistics.v1.{_clock.Now:yyyy-MM-dd HH.mm.ss}.json"); + var filename = _fileSystem.Path.Combine(_basePath, $"statistics.v1.{_clock.Now:yyyy-MM-dd HH.mm.ss}.json"); - if (!Directory.Exists(_basePath)) + if (!_fileSystem.Directory.Exists(_basePath)) { try { _logger.LogDebug("Try Create directory '{basePath}'.", _basePath); - Directory.CreateDirectory(_basePath); + _fileSystem.Directory.CreateDirectory(_basePath); } catch (Exception e) { @@ -104,11 +111,11 @@ private IDisposable WriteEventsToFile() } } - if (Directory.Exists(_basePath)) + if (_fileSystem.Directory.Exists(_basePath)) { try { - File.WriteAllText(filename, json); + _fileSystem.File.WriteAllText(filename, json); } catch (Exception e) { diff --git a/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj b/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj index 5a72cb03..41560e25 100644 --- a/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj +++ b/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj index e45bc1a3..2780ae94 100644 --- a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj +++ b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj index cf0b7d2c..754785ec 100644 --- a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj +++ b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj index 12615565..f72dec1e 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj +++ b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs b/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs index 14c58a87..0046cda4 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs @@ -1,6 +1,7 @@ namespace RepoM.Plugin.Statistics.Tests; using System; +using System.IO.Abstractions; using FakeItEasy; using Microsoft.Extensions.Logging; using RepoM.Core.Plugin.Common; @@ -44,5 +45,6 @@ private static void RegisterExternals(Container container) container.RegisterSingleton(A.Dummy); container.RegisterSingleton(A.Dummy); container.RegisterSingleton(A.Dummy>); + container.RegisterSingleton(A.Dummy); } } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj index 7ead70a6..7fc97221 100644 --- a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj +++ b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj @@ -20,8 +20,8 @@ - - + + From 57d301b7515cca1dbe3b3d755c580aa7e426b7c1 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 21:27:14 +0100 Subject: [PATCH 41/60] add tests --- .../StatisticsModule.cs | 21 +++++++----- .../StatisticsService.cs | 7 ++++ .../StatisticsModuleTest.cs | 33 +++++++++++++++++++ 3 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs diff --git a/src/RepoM.Plugin.Statistics/StatisticsModule.cs b/src/RepoM.Plugin.Statistics/StatisticsModule.cs index e93d47fc..5111d51c 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsModule.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsModule.cs @@ -21,7 +21,7 @@ internal class StatisticsModule : IModule private readonly IClock _clock; private readonly IAppDataPathProvider _pathProvider; private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger _logger; private string _basePath = string.Empty; private IDisposable? _disposable; private readonly JsonSerializerSettings _settings; @@ -31,7 +31,7 @@ public StatisticsModule( IClock clock, IAppDataPathProvider pathProvider, IFileSystem fileSystem, - ILogger logger) + ILogger logger) { _service = service ?? throw new ArgumentNullException(nameof(service)); _clock = clock ?? throw new ArgumentNullException(nameof(clock)); @@ -56,8 +56,19 @@ public async Task StartAsync() await ProcessEventsFromFile().ConfigureAwait(false); } + public Task StopAsync() + { + _disposable?.Dispose(); + return Task.CompletedTask; + } + private async Task ProcessEventsFromFile() { + if (!_fileSystem.Directory.Exists(_basePath)) + { + return; + } + IOrderedEnumerable orderedEnumerable = _fileSystem.Directory.GetFiles(_basePath, "statistics.v1.*.json").OrderBy(f => f); foreach (var file in orderedEnumerable) @@ -124,10 +135,4 @@ private IDisposable WriteEventsToFile() } }); } - - public Task StopAsync() - { - _disposable?.Dispose(); - return Task.CompletedTask; - } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs index 4aca9b15..31dbfd1f 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsService.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -3,7 +3,9 @@ namespace RepoM.Plugin.Statistics; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.Immutable; using System.Collections.ObjectModel; +using System.Linq; using System.Reactive.Subjects; using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.Repository; @@ -36,6 +38,11 @@ public void Record(IRepository repository) _events.OnNext(evt); } + public IReadOnlyList GetRepositories() + { + return _recordings.Select(x => x.Key).ToImmutableArray(); + } + public IReadOnlyList GetRecordings(IRepository repository) { if (_recordings.TryGetValue(repository.SafePath, out RepositoryStatistics? repositoryStatistics)) diff --git a/tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs b/tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs new file mode 100644 index 00000000..e29c869b --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs @@ -0,0 +1,33 @@ +namespace RepoM.Plugin.Statistics.Tests; + +using System.IO.Abstractions; +using System.IO.Abstractions.TestingHelpers; +using System.Threading.Tasks; +using FakeItEasy; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using RepoM.Core.Plugin.Common; +using Xunit; +using IClock = RepoM.Core.Plugin.Common.IClock; + +public class StatisticsModuleTest +{ + [Fact] + public async Task StartAsync_ShouldInitialize() + { + // arrange + IClock clock = A.Fake(); + IAppDataPathProvider pathProvider = A.Fake(); + A.CallTo(() => pathProvider.GetAppDataPath()).Returns("C:\\data"); + IFileSystem fileSystem = new MockFileSystem(); + ILogger logger = A.Fake(); + var statisticsService = new StatisticsService(clock); + var sut = new StatisticsModule(statisticsService, clock, pathProvider, fileSystem, logger); + + // act + await sut.StartAsync(); + + // assert + statisticsService.GetRepositories().Should().BeEmpty(); + } +} \ No newline at end of file From 112669b31099292646e063b51c32220bbd210ff5 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 21:29:02 +0100 Subject: [PATCH 42/60] fix test --- .../StatisticsModuleTest.cs | 20 +++++++++++++------ .../StatisticsPackageTest.cs | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs b/tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs index e29c869b..4202e2bd 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/StatisticsModuleTest.cs @@ -12,17 +12,25 @@ namespace RepoM.Plugin.Statistics.Tests; public class StatisticsModuleTest { + private readonly IClock _clock; + private readonly IAppDataPathProvider _pathProvider; + private readonly ILogger _logger; + + public StatisticsModuleTest() + { + _clock = A.Fake(); + _pathProvider = A.Fake(); + A.CallTo(() => _pathProvider.GetAppDataPath()).Returns("C:\\data"); + _logger = A.Fake(); + } + [Fact] public async Task StartAsync_ShouldInitialize() { // arrange - IClock clock = A.Fake(); - IAppDataPathProvider pathProvider = A.Fake(); - A.CallTo(() => pathProvider.GetAppDataPath()).Returns("C:\\data"); IFileSystem fileSystem = new MockFileSystem(); - ILogger logger = A.Fake(); - var statisticsService = new StatisticsService(clock); - var sut = new StatisticsModule(statisticsService, clock, pathProvider, fileSystem, logger); + var statisticsService = new StatisticsService(_clock); + var sut = new StatisticsModule(statisticsService, _clock, _pathProvider, fileSystem, _logger); // act await sut.StartAsync(); diff --git a/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs b/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs index 0046cda4..0e762bf5 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/StatisticsPackageTest.cs @@ -44,7 +44,7 @@ private static void RegisterExternals(Container container) { container.RegisterSingleton(A.Dummy); container.RegisterSingleton(A.Dummy); - container.RegisterSingleton(A.Dummy>); + container.RegisterSingleton(A.Dummy); container.RegisterSingleton(A.Dummy); } } \ No newline at end of file From 11e76b77a5a08738255521b63ed88739b3b00d9b Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Tue, 6 Dec 2022 21:39:54 +0100 Subject: [PATCH 43/60] Add test --- .../RepoM.Plugin.Statistics.Tests.csproj | 4 + ...rdStatisticsActionExecutorDecoratorTest.cs | 78 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 tests/RepoM.Plugin.Statistics.Tests/RepositoryActions/RecordStatisticsActionExecutorDecoratorTest.cs diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj index f72dec1e..22a7c61e 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj +++ b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj @@ -34,4 +34,8 @@ + + + + diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepositoryActions/RecordStatisticsActionExecutorDecoratorTest.cs b/tests/RepoM.Plugin.Statistics.Tests/RepositoryActions/RecordStatisticsActionExecutorDecoratorTest.cs new file mode 100644 index 00000000..51f2d17c --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/RepositoryActions/RecordStatisticsActionExecutorDecoratorTest.cs @@ -0,0 +1,78 @@ +namespace RepoM.Plugin.Statistics.Tests.RepositoryActions; + +using System; +using FakeItEasy; +using FluentAssertions; +using RepoM.Core.Plugin.Common; +using RepoM.Core.Plugin.Repository; +using RepoM.Core.Plugin.RepositoryActions; +using RepoM.Core.Plugin.RepositoryActions.Actions; +using RepoM.Plugin.Statistics.RepositoryActions; +using Xunit; + +public class RecordStatisticsActionExecutorDecoratorTest +{ + private readonly IClock _clock; + private readonly IRepository _repository; + private readonly DateTime _now = DateTime.Now; + + public RecordStatisticsActionExecutorDecoratorTest() + { + _clock = A.Dummy(); + A.CallTo(() => _clock.Now).Returns(_now); + _repository = A.Fake(); + A.CallTo(() => _repository.SafePath).Returns("C:/path/repo"); + } + + [Fact] + public void Execute_ShouldCallExecuteOnDecorateeWithSameArguments() + { + // arrange + IActionExecutor decoratee = A.Fake>(); + var service = new StatisticsService(_clock); + var sut = new RecordStatisticsActionExecutorDecorator(decoratee, service); + + // act + var action = new DummyAction(); + sut.Execute(_repository, action); + + // assert + _ = A.CallTo(() => decoratee.Execute(_repository, action)).MustHaveHappenedOnceExactly(); + } + + [Fact] + public void Execute_ShouldRecordWhenTypeIsNotNullType() + { + // arrange + IActionExecutor decoratee = A.Fake>(); + var service = new StatisticsService(_clock); + var sut = new RecordStatisticsActionExecutorDecorator(decoratee, service); + + // act + + var action = new DummyAction(); + sut.Execute(_repository, action); + + // assert + service.GetRecordings(_repository).Should().BeEquivalentTo(new[] { _now, }); + } + + [Fact] + public void Execute_ShouldNotRecordWhenTypeIsNullType() + { + // arrange + IActionExecutor decoratee = A.Fake>(); + var service = new StatisticsService(_clock); + var sut = new RecordStatisticsActionExecutorDecorator(decoratee, service); + + // act + sut.Execute(_repository, NullAction.Instance); + + // assert + service.GetRecordings(_repository).Should().BeEmpty(); + } +} + +public class DummyAction : IAction +{ +} \ No newline at end of file From 368728b2f2102ca8f6e50e1e18e5808f2347308d Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 7 Dec 2022 21:39:36 +0100 Subject: [PATCH 44/60] added tests --- .../Common/FileAppSettingsService.cs | 2 +- .../Ordering/LastOpenedConfigurationV1.cs | 4 - .../Ordering/IntegrationTest.cs | 82 +++++++++++++++++++ .../Ordering/MockFileDataFactory.cs | 34 ++++++++ ...nTest.LastOpenedConfiguration.testfile.yml | 3 + ...Test.LastOpenedConfiguration1.testfile.yml | 3 + .../Ordering/UsageScorerFactoryTest.cs | 32 ++++++++ ...nTest.LastOpenedConfiguration.verified.txt | 6 ++ ...Test.LastOpenedConfiguration1.verified.txt | 6 ++ .../RepoM.Plugin.Statistics.Tests.csproj | 2 +- 10 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/IntegrationTest.cs create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/MockFileDataFactory.cs create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration.testfile.yml create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration1.testfile.yml create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration.verified.txt create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration1.verified.txt diff --git a/src/RepoM.Api/Common/FileAppSettingsService.cs b/src/RepoM.Api/Common/FileAppSettingsService.cs index 74f49b95..b172d510 100644 --- a/src/RepoM.Api/Common/FileAppSettingsService.cs +++ b/src/RepoM.Api/Common/FileAppSettingsService.cs @@ -32,7 +32,7 @@ public FilesICompareSettingsService(IAppDataPathProvider appDataPathProvider, IF private string GetFileName() { - return Path.Combine(_appDataPathProvider.GetAppDataPath(), "RepoM.Ordering.yaml"); + return _fileSystem.Path.Combine(_appDataPathProvider.GetAppDataPath(), "RepoM.Ordering.yaml"); } private Dictionary Load() diff --git a/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs index f966dfc7..d36d6915 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/LastOpenedConfigurationV1.cs @@ -4,9 +4,5 @@ namespace RepoM.Plugin.Statistics.Ordering; public sealed class LastOpenedConfigurationV1 : IRepositoriesComparerConfiguration { - public LastOpenedConfigurationV1() - { - } - public int Weight { get; set; } } \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/IntegrationTest.cs b/tests/RepoM.Plugin.Statistics.Tests/Ordering/IntegrationTest.cs new file mode 100644 index 00000000..ea889bb6 --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/IntegrationTest.cs @@ -0,0 +1,82 @@ +namespace RepoM.Plugin.Statistics.Tests.Ordering; + +using System.Collections.Generic; +using FakeItEasy; +using System.IO.Abstractions; +using System.IO.Abstractions.TestingHelpers; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using RepoM.Api.Common; +using RepoM.Core.Plugin.Common; +using SimpleInjector; +using Xunit; +using VerifyXunit; +using EasyTestFileXunit; +using EasyTestFile; +using VerifyTests; +using RepoM.Api.Tests.IO.ModuleBasedRepositoryActionProvider; +using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; +using RepoM.Core.Plugin.RepositoryOrdering.Configuration; + +[UsesEasyTestFile] +[UsesVerify] +public class IntegrationTest +{ + private readonly IAppDataPathProvider _appDataPathProvider; + private readonly MockFileSystem _fileSystem; + private readonly FilesICompareSettingsService _sut; + private readonly EasyTestFileSettings _testFileSettings; + private readonly VerifySettings _verifySettings; + + public IntegrationTest() + { + var container = new Container(); + new StatisticsPackage().RegisterServices(container); + + _appDataPathProvider = A.Fake(); + _fileSystem = new MockFileSystem(); + container.Register(Lifestyle.Singleton); + container.RegisterSingleton(A.Dummy); + container.RegisterInstance(_appDataPathProvider); + container.RegisterSingleton(A.Dummy); + container.RegisterInstance(_fileSystem); + + A.CallTo(() => _appDataPathProvider.GetAppDataPath()).Returns("C:\\\\dir"); + + container.Verify(); + + _sut = container.GetInstance(); + + _testFileSettings = new EasyTestFileSettings(); + _testFileSettings.UseDirectory("TestFiles"); + _testFileSettings.UseExtension("yml"); + + _verifySettings = new VerifySettings(); + _verifySettings.UseDirectory("Verified"); + } + + [Fact] + public async Task LastOpenedConfiguration() + { + // arrange + await _fileSystem.AddEasyFile("C:\\\\dir\\RepoM.Ordering.yaml", _testFileSettings); + + // act + Dictionary result =_sut.Configuration; + + // assert + await Verifier.Verify(result, _verifySettings); + } + [Fact] + public async Task LastOpenedConfiguration1() + { + // arrange + await _fileSystem.AddEasyFile("C:\\\\dir\\RepoM.Ordering.yaml", _testFileSettings); + + // act + Dictionary result =_sut.Configuration; + + // assert + await Verifier.Verify(result, _verifySettings); + } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/MockFileDataFactory.cs b/tests/RepoM.Plugin.Statistics.Tests/Ordering/MockFileDataFactory.cs new file mode 100644 index 00000000..2832c843 --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/MockFileDataFactory.cs @@ -0,0 +1,34 @@ +namespace RepoM.Plugin.Statistics.Tests.Ordering; + +using System.IO; +using System.IO.Abstractions.TestingHelpers; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using EasyTestFile; +using EasyTestFileXunit; + +internal static class MockFileDataFactory +{ + public static async Task AddEasyFile( + this MockFileSystem fs, + string filename, + EasyTestFileSettings? settings = null, + [CallerFilePath] string sourceFile = "", + [CallerMemberName] string method = "") + { + await using Stream stream = await EasyTestFile.LoadAsStream(settings, sourceFile, method); + fs.AddFile(filename, new MockFileData(StreamToBytes(stream))); + } + + private static byte[] StreamToBytes(Stream input) + { + if (input is MemoryStream ms) + { + return ms.ToArray(); + } + + using var ms1 = new MemoryStream(); + input.CopyTo(ms1); + return ms1.ToArray(); + } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration.testfile.yml b/tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration.testfile.yml new file mode 100644 index 00000000..e79e0354 --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration.testfile.yml @@ -0,0 +1,3 @@ +Name1: + !last-opened-comparer@1 + weight: 1 \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration1.testfile.yml b/tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration1.testfile.yml new file mode 100644 index 00000000..f809ce3f --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/TestFiles/IntegrationTest.LastOpenedConfiguration1.testfile.yml @@ -0,0 +1,3 @@ +Name1: + !last-opened-comparer@1 + weight: 123 \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs new file mode 100644 index 00000000..66cb936c --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs @@ -0,0 +1,32 @@ +namespace RepoM.Plugin.Statistics.Tests.Ordering; + +using FakeItEasy; +using FluentAssertions; +using RepoM.Core.Plugin.Common; +using RepoM.Core.Plugin.RepositoryOrdering; +using RepoM.Plugin.Statistics.Ordering; +using Xunit; + +public class UsageScorerFactoryTest +{ + private readonly StatisticsService _service; + + public UsageScorerFactoryTest() + { + _service = new StatisticsService(A.Fake()); + } + + [Fact] + public void Create_ShouldReturnInstanceOfUsageScoreCalculator() + { + // arrange + var sut = new UsageScorerFactory(_service); + var config = new UsageScorerConfigurationV1(); + + // act + IRepositoryScoreCalculator result = sut.Create(config); + + // assert + result.Should().BeOfType(); + } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration.verified.txt b/tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration.verified.txt new file mode 100644 index 00000000..b33bb04f --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration.verified.txt @@ -0,0 +1,6 @@ +{ + Name1: { + $type: LastOpenedConfigurationV1, + Weight: 1 + } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration1.verified.txt b/tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration1.verified.txt new file mode 100644 index 00000000..187bda01 --- /dev/null +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/Verified/IntegrationTest.LastOpenedConfiguration1.verified.txt @@ -0,0 +1,6 @@ +{ + Name1: { + $type: LastOpenedConfigurationV1, + Weight: 123 + } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj index 22a7c61e..06485762 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj +++ b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj @@ -35,7 +35,7 @@ - + From a543a54234b755828e847243166c8a0f5fa4e549 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 7 Dec 2022 21:44:17 +0100 Subject: [PATCH 45/60] Remove poc project --- RepoM.sln | 22 --- .../DummyEvent.cs | 2 +- tests/Yaml.Poc.Tests/DI/Bootstrapper.cs | 126 ------------------ .../TestFramework/VerifierInitializer.cs | 15 --- tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj | 44 ------ .../Yaml.Poc.Tests/YamlTests.Abc.verified.txt | 16 --- .../Yaml.Poc.Tests/YamlTests.DI.verified.txt | 16 --- tests/Yaml.Poc.Tests/YamlTests.cs | 111 --------------- 8 files changed, 1 insertion(+), 351 deletions(-) delete mode 100644 tests/Yaml.Poc.Tests/DI/Bootstrapper.cs delete mode 100644 tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs delete mode 100644 tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj delete mode 100644 tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt delete mode 100644 tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt delete mode 100644 tests/Yaml.Poc.Tests/YamlTests.cs diff --git a/RepoM.sln b/RepoM.sln index 2f1361ec..7bbbd73a 100644 --- a/RepoM.sln +++ b/RepoM.sln @@ -33,8 +33,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Api.Tests", "tests\Re EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Core.Plugin", "src\RepoM.Core.Plugin\RepoM.Core.Plugin.csproj", "{E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yaml.Poc.Tests", "tests\Yaml.Poc.Tests\Yaml.Poc.Tests.csproj", "{C5A65FD2-CD65-47EA-A521-8B7C756AC986}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.Statistics", "src\RepoM.Plugin.Statistics\RepoM.Plugin.Statistics.csproj", "{DF4F5FA8-0E3F-4D84-A048-20242FD032BC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RepoM.Plugin.Statistics.Tests", "tests\RepoM.Plugin.Statistics.Tests\RepoM.Plugin.Statistics.Tests.csproj", "{C90AA844-B355-4C62-96FA-D4F338EE094A}" @@ -333,26 +331,6 @@ Global {E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}.Release|x64.Build.0 = Release|Any CPU {E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}.Release|x86.ActiveCfg = Release|Any CPU {E38D9928-A0A6-4978-BD7E-C7F2E2B6BC9B}.Release|x86.Build.0 = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM.ActiveCfg = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM.Build.0 = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|ARM64.Build.0 = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x64.ActiveCfg = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x64.Build.0 = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x86.ActiveCfg = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Debug|x86.Build.0 = Debug|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|Any CPU.Build.0 = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM.ActiveCfg = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM.Build.0 = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM64.ActiveCfg = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|ARM64.Build.0 = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x64.ActiveCfg = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x64.Build.0 = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x86.ActiveCfg = Release|Any CPU - {C5A65FD2-CD65-47EA-A521-8B7C756AC986}.Release|x86.Build.0 = Release|Any CPU {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF4F5FA8-0E3F-4D84-A048-20242FD032BC}.Debug|ARM.ActiveCfg = Debug|Any CPU diff --git a/tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs b/tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs index 18ac45b7..c3c3afb1 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/DummyEvent.cs @@ -5,7 +5,7 @@ namespace RepoM.Plugin.Statistics.Tests; internal class DummyEvent : IEvent { - public string Repository { get; set; } + public string Repository { get; set; } = null!; public DateTime Timestamp { get; set; } } \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs b/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs deleted file mode 100644 index bdf1829c..00000000 --- a/tests/Yaml.Poc.Tests/DI/Bootstrapper.cs +++ /dev/null @@ -1,126 +0,0 @@ -namespace Yaml.Poc.Tests.DI; - -using System; -using System.Threading.Tasks; -using RepoM.Api.Git; -using RepoM.Api.Ordering.Az; -using RepoM.Api.Ordering.Composition; -using RepoM.Api.Ordering.IsPinned; -using RepoM.Api.Ordering.Label; -using RepoM.Api.Ordering.Score; -using RepoM.Api.Ordering.Sum; -using RepoM.Core.Plugin.RepositoryOrdering; -using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using SimpleInjector; -using Container = SimpleInjector.Container; - - -internal class RepositoryComparerCompositionFactory : IRepositoryComparerFactory -{ - private readonly Container _container; - - public RepositoryComparerCompositionFactory(Container container) - { - _container = container; - } - - public IRepositoryComparer Create(IRepositoriesComparerConfiguration configuration) - { - Type type = typeof(IRepositoryComparerFactory<>).MakeGenericType(configuration.GetType()); - dynamic factory = _container.GetInstance(type); - return factory.Create((dynamic)configuration); - } -} - -internal class RepositoryScoreCalculatorFactory : IRepositoryScoreCalculatorFactory -{ - private readonly Container _container; - - public RepositoryScoreCalculatorFactory(Container container) - { - _container = container; - } - - public IRepositoryScoreCalculator Create(IRepositoryScorerConfiguration configuration) - { - Type type = typeof(IRepositoryScoreCalculatorFactory<>).MakeGenericType(configuration.GetType()); - dynamic factory = _container.GetInstance(type); - return factory.Create((dynamic)configuration); - } - -} - -internal class DummyIRepositoryMonitor : IRepositoryMonitor -{ - public event EventHandler? OnChangeDetected; - public event EventHandler? OnDeletionDetected; - public event EventHandler? OnScanStateChanged; - public void Stop() - { - throw new NotImplementedException(); - } - - public void Observe() - { - throw new NotImplementedException(); - } - - public void Reset() - { - throw new NotImplementedException(); - } - - public Task ScanForLocalRepositoriesAsync() - { - throw new NotImplementedException(); - } - - public void IgnoreByPath(string path) - { - throw new NotImplementedException(); - } - - public void SetPinned(bool newValue, Repository repository) - { - throw new NotImplementedException(); - } - - public bool IsPinned(Repository repository) - { - throw new NotImplementedException(); - } -} - -internal static class Bootstrapper -{ - public static void RegisterOrderingConfiguration(Container container) - { - container.RegisterSingleton(); - container.RegisterSingleton(); - - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, AzRepositoryComparerFactory>(Lifestyle.Singleton); - container.Register, AzRepositoryComparerFactory>(Lifestyle.Singleton); - - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); - container.Register, CompositionRepositoryComparerFactory>(Lifestyle.Singleton); - - container.Register(Lifestyle.Singleton); - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, IsPinnedScorerFactory>(Lifestyle.Singleton); - container.Register, IsPinnedScorerFactory>(Lifestyle.Singleton); - - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, TagScorerFactory>(Lifestyle.Singleton); - container.Register, TagScorerFactory>(Lifestyle.Singleton); - - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); - container.Register, ScoreRepositoryComparerFactory>(Lifestyle.Singleton); - - container.Collection.Append(Lifestyle.Singleton); - container.Collection.Append, SumRepositoryComparerFactory>(Lifestyle.Singleton); - container.Register, SumRepositoryComparerFactory>(Lifestyle.Singleton); - } -} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs b/tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs deleted file mode 100644 index b2d0afc3..00000000 --- a/tests/Yaml.Poc.Tests/TestFramework/VerifierInitializer.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Yaml.Poc.Tests.TestFramework; - -using System.Runtime.CompilerServices; -using Argon; -using VerifyTests; - -public static class VerifierInitializer -{ - [ModuleInitializer] - public static void Initialize() - { - VerifierSettings.DisableRequireUniquePrefix(); - VerifierSettings.AddExtraSettings(serializerSettings => serializerSettings.TypeNameHandling = TypeNameHandling.Auto); - } -} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj b/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj deleted file mode 100644 index 7fc97221..00000000 --- a/tests/Yaml.Poc.Tests/Yaml.Poc.Tests.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - net6.0 - false - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - - - - - diff --git a/tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt b/tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt deleted file mode 100644 index 7709a59c..00000000 --- a/tests/Yaml.Poc.Tests/YamlTests.Abc.verified.txt +++ /dev/null @@ -1,16 +0,0 @@ -{ - Comparers: [ - { - $type: AlphabetComparerConfigurationV1, - Property: Name, - Weight: 5 - }, - { - $type: ScoreComparerConfigurationV1, - ScoreProvider: { - $type: IsPinnedScorerConfigurationV1, - Weight: 5 - } - } - ] -} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt b/tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt deleted file mode 100644 index 654929da..00000000 --- a/tests/Yaml.Poc.Tests/YamlTests.DI.verified.txt +++ /dev/null @@ -1,16 +0,0 @@ -{ - Comparers: [ - { - $type: AlphabetComparerConfigurationV1, - Property: Name, - Weight: 1 - }, - { - $type: ScoreComparerConfigurationV1, - ScoreProvider: { - $type: IsPinnedScorerConfigurationV1, - Weight: 5 - } - } - ] -} \ No newline at end of file diff --git a/tests/Yaml.Poc.Tests/YamlTests.cs b/tests/Yaml.Poc.Tests/YamlTests.cs deleted file mode 100644 index 56f25c03..00000000 --- a/tests/Yaml.Poc.Tests/YamlTests.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace Yaml.Poc.Tests; - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using RepoM.Api.Ordering.Az; -using RepoM.Api.Ordering.IsPinned; -using RepoM.Api.Ordering.Score; -using RepoM.Api.Ordering.Sum; -using RepoM.Core.Plugin.Repository; -using RepoM.Core.Plugin.RepositoryOrdering; -using RepoM.Core.Plugin.RepositoryOrdering.Configuration; -using SimpleInjector; -using VerifyXunit; -using Xunit; -using Yaml.Poc.Tests.DI; -using YamlDotNet.Serialization; -using YamlDotNet.Serialization.NamingConventions; - -[UsesVerify] -public class YamlTests -{ - private const string YML = @" - !sum-comparer@1 - comparers: - - !az-comparer@1 - property: Name - weight: 5 - - !score-comparer@1 - score-provider: - !is-pinned-scorer@1 - weight: 5 -"; - - private const string YML1 = @" - !sum-comparer@1 - comparers: - - !az-comparer@1 - property: Name - weight: 1 - - !score-comparer@1 - score-provider: - !is-pinned-scorer@1 - weight: 5 -"; - - //https://github.com/aaubry/YamlDotNet/wiki/Serialization.Deserializer - [Fact] - public async Task Abc() - { - IDeserializer deserializer = new DeserializerBuilder() - .WithNamingConvention(HyphenatedNamingConvention.Instance) - .WithTagMapping("!score-comparer@1", typeof(ScoreComparerConfigurationV1)) - .WithTagMapping("!az-comparer@1", typeof(AlphabetComparerConfigurationV1)) - .WithTagMapping("!sum-comparer@1", typeof(SumComparerConfigurationV1)) - .WithTagMapping("!is-pinned-scorer@1", typeof(IsPinnedScorerConfigurationV1)) - .Build(); - - var result = deserializer.Deserialize(YML); - - await Verifier.Verify(result); - } - - - [Fact] - public async Task DI() - { - var container = new Container(); - Bootstrapper.RegisterOrderingConfiguration(container); - container.Verify(); - - DeserializerBuilder builder = new DeserializerBuilder() - .WithNamingConvention(HyphenatedNamingConvention.Instance); - - foreach (IConfigurationRegistration instance in container.GetAllInstances()) - { - var tag = instance.Tag.TrimStart('!'); - builder.WithTagMapping("!" + tag, instance.ConfigurationType); - } - - IDeserializer deserializer = builder.Build(); - - IRepositoriesComparerConfiguration result = deserializer.Deserialize(YML1); - // var instance2s = container.GetAllInstances>(); - // IRepositoryComparerFactory - await Verifier.Verify(result); - - IRepositoryComparerFactory factory = container.GetInstance(); - var comparer = factory.Create(result); - - var repo = new R { Name = "rrrr", IsPinned = true,}; - var repo2 = new R { Name = "Coen", IsPinned = false, }; - - int r = comparer.Compare(repo, repo2); - } -} - -public class R : IRepository -{ - public string Name { get; set; } - public string Location { get; } - public string CurrentBranch { get; set; } - public string[] Branches { get; } - public string[] LocalBranches { get; } - public string SafePath { get; } - public string Path { get; set; } - public bool IsPinned { get; set; } - public bool HasUnpushedChanges { get; set; } - public string[] Tags { get; set; } = Array.Empty(); - public List Remotes { get; } = new(0); -} \ No newline at end of file From fa9e2a53edf9797f7912c8e34167376328c555fd Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 7 Dec 2022 21:53:00 +0100 Subject: [PATCH 46/60] .. --- src/RepoM.App/Controls/AcrylicContextMenu.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/RepoM.App/Controls/AcrylicContextMenu.cs b/src/RepoM.App/Controls/AcrylicContextMenu.cs index 6934e356..b730a7cd 100644 --- a/src/RepoM.App/Controls/AcrylicContextMenu.cs +++ b/src/RepoM.App/Controls/AcrylicContextMenu.cs @@ -12,6 +12,4 @@ protected override void OnOpened(RoutedEventArgs e) AcrylicHelper.EnableBlur(this); } - - } \ No newline at end of file From 45ad5ae7fc3feb6c835144d5e8c4fa37311fca30 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 7 Dec 2022 22:10:56 +0100 Subject: [PATCH 47/60] persist sort key --- .../RepositoryOrdering/RepositoryComparerManager.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs index b2436cce..576175b6 100644 --- a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs +++ b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs @@ -4,6 +4,7 @@ namespace RepoM.App.RepositoryOrdering; using System.Collections; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Logging; using RepoM.Api.Common; using RepoM.Api.Ordering.Az; using RepoM.Core.Plugin.RepositoryOrdering; @@ -12,15 +13,18 @@ namespace RepoM.App.RepositoryOrdering; internal class RepositoryComparerManager : IRepositoryComparerManager { private readonly IAppSettingsService _appSettingsService; + private readonly ILogger _logger; private readonly ComparerComposition _comparer; private readonly List _repositoryComparerKeys; public RepositoryComparerManager( IAppSettingsService appSettingsService, ICompareSettingsService compareSettingsService, - IRepositoryComparerFactory repositoryComparerFactory) + IRepositoryComparerFactory repositoryComparerFactory, + ILogger logger) { _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); if (compareSettingsService == null) { @@ -68,7 +72,10 @@ public RepositoryComparerManager( _repositoryComparerKeys = comparers.Select(x => x.Key).ToList(); - SelectedRepositoryComparerKey = _repositoryComparerKeys.First(); + if (!SetRepositoryComparer(_appSettingsService.SortKey)) + { + SetRepositoryComparer(_repositoryComparerKeys.First()); + } } public event EventHandler? SelectedRepositoryComparerKeyChanged; @@ -86,9 +93,9 @@ public bool SetRepositoryComparer(string key) return false; } + _appSettingsService.SortKey = key; SelectedRepositoryComparerKey = key; SelectedRepositoryComparerKeyChanged?.Invoke(this, key); return true; - } } \ No newline at end of file From 79d20eb759081f77e5d5221d9d1363394e983b18 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Wed, 7 Dec 2022 22:12:41 +0100 Subject: [PATCH 48/60] .. --- src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs index 576175b6..276bc870 100644 --- a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs +++ b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs @@ -82,7 +82,7 @@ public RepositoryComparerManager( public IComparer Comparer => _comparer; - public string SelectedRepositoryComparerKey { get; private set; } + public string SelectedRepositoryComparerKey { get; private set; } = "Default"; public IReadOnlyList RepositoryComparerKeys => _repositoryComparerKeys; From 024c6f7a20a8756124842c152b73a44848ae70f0 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Thu, 8 Dec 2022 22:07:16 +0100 Subject: [PATCH 49/60] simple injector upgrade --- RepoM.sln.DotSettings | 1 + src/RepoM.Api/RepoM.Api.csproj | 2 +- src/RepoM.App/App.xaml.cs | 10 +- src/RepoM.App/RepoM.App.csproj | 3 +- .../RepositoryComparerManager.cs | 30 ++-- .../RepoM.Core.Plugin.csproj | 1 + .../SimpleInjector/IPackage.cs | 36 +++++ .../SimpleInjector/PackageExtensions.cs | 147 ++++++++++++++++++ .../AzureDevOpsPackage.cs | 1 + .../RepoM.Plugin.AzureDevOps.csproj | 2 - .../RepoM.Plugin.EverythingFileSearch.csproj | 2 - .../RepoM.Plugin.LuceneSearch.csproj | 2 - .../RepoM.Plugin.SonarCloud.csproj | 2 - .../RepoM.Plugin.Statistics.csproj | 4 +- ...RepoM.Plugin.WindowsExplorerGitInfo.csproj | 2 - 15 files changed, 210 insertions(+), 35 deletions(-) create mode 100644 src/RepoM.Core.Plugin/SimpleInjector/IPackage.cs create mode 100644 src/RepoM.Core.Plugin/SimpleInjector/PackageExtensions.cs diff --git a/RepoM.sln.DotSettings b/RepoM.sln.DotSettings index d49b350a..abeb3a9d 100644 --- a/RepoM.sln.DotSettings +++ b/RepoM.sln.DotSettings @@ -1,5 +1,6 @@  True + True True True True diff --git a/src/RepoM.Api/RepoM.Api.csproj b/src/RepoM.Api/RepoM.Api.csproj index 5531719f..00dd3765 100644 --- a/src/RepoM.Api/RepoM.Api.csproj +++ b/src/RepoM.Api/RepoM.Api.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/RepoM.App/App.xaml.cs b/src/RepoM.App/App.xaml.cs index e4293a75..426c84df 100644 --- a/src/RepoM.App/App.xaml.cs +++ b/src/RepoM.App/App.xaml.cs @@ -94,7 +94,10 @@ protected override void OnStartup(StartupEventArgs e) logger.LogInformation("Started"); RegisterLogging(loggerFactory); RegisterServices(_container, fileSystem); + +#if DEBUG _container.Verify(VerificationOption.VerifyAndDiagnose); +#endif UseRepositoryMonitor(_container); @@ -149,9 +152,9 @@ protected override void OnExit(ExitEventArgs e) _hotkey?.Unregister(); -#pragma warning disable CA1416 // Validate platform compatibility +// #pragma warning disable CA1416 // Validate platform compatibility _notifyIcon?.Dispose(); -#pragma warning restore CA1416 // Validate platform compatibility +// #pragma warning restore CA1416 // Validate platform compatibility base.OnExit(e); } @@ -302,8 +305,7 @@ private static void RegisterServices(Container container, IFileSystem fileSystem typeof(IActionExecutor<>), typeof(LoggerActionExecutorDecorator<>), Lifestyle.Singleton); - - + IEnumerable pluginDlls = PluginFinder.FindPluginAssemblies(Path.Combine(AppDomain.CurrentDomain.BaseDirectory), fileSystem); IEnumerable assemblies = pluginDlls.Select(plugin => Assembly.Load(AssemblyName.GetAssemblyName(plugin.FullName))); container.RegisterPackages(assemblies); diff --git a/src/RepoM.App/RepoM.App.csproj b/src/RepoM.App/RepoM.App.csproj index bda3d056..4cdc8ee8 100644 --- a/src/RepoM.App/RepoM.App.csproj +++ b/src/RepoM.App/RepoM.App.csproj @@ -43,7 +43,6 @@ - @@ -51,7 +50,7 @@ - + diff --git a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs index 276bc870..7a7e9b37 100644 --- a/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs +++ b/src/RepoM.App/RepositoryOrdering/RepositoryComparerManager.cs @@ -24,18 +24,10 @@ public RepositoryComparerManager( ILogger logger) { _appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); + _ = compareSettingsService ?? throw new ArgumentNullException(nameof(compareSettingsService)); + _ = repositoryComparerFactory ?? throw new ArgumentNullException(nameof(repositoryComparerFactory)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - if (compareSettingsService == null) - { - throw new ArgumentNullException(nameof(compareSettingsService)); - } - - if (repositoryComparerFactory == null) - { - throw new ArgumentNullException(nameof(repositoryComparerFactory)); - } - Dictionary multipleConfigurations = new (); var comparers = new Dictionary(); @@ -45,7 +37,7 @@ public RepositoryComparerManager( } catch (Exception e) { - Console.WriteLine(e); + _logger.LogError(e, "Could not get comparer configuration. Falling back to default. {message}", e.Message); } foreach ((var key, IRepositoriesComparerConfiguration config) in multipleConfigurations) @@ -54,26 +46,33 @@ public RepositoryComparerManager( { if (!comparers.TryAdd(key, new RepositoryComparerAdapter(repositoryComparerFactory.Create(config)))) { - // swallow + _logger.LogWarning("Could not add comparer for key '{key}'.", key); } } - catch (Exception) + catch (Exception e) { - // swallow + _logger.LogError(e, "Could not create a repository comparer for key '{key}'. {message}", key, e.Message); } } if (comparers.Count == 0) { comparers.Add("Default", new RepositoryComparerAdapter(new AzComparer(1, "Name"))); + _logger.LogInformation("No custom comparers added, add default comparer"); } _comparer = new ComparerComposition(comparers); _repositoryComparerKeys = comparers.Select(x => x.Key).ToList(); - if (!SetRepositoryComparer(_appSettingsService.SortKey)) + if (string.IsNullOrWhiteSpace(_appSettingsService.SortKey)) + { + _logger.LogInformation("Custom sorter key was not set. Pick first one."); + SetRepositoryComparer(_repositoryComparerKeys.First()); + } + else if (!SetRepositoryComparer(_appSettingsService.SortKey)) { + _logger.LogInformation("Could not set comparer '{key}'. Falling back to first comparer.", _appSettingsService.SortKey); SetRepositoryComparer(_repositoryComparerKeys.First()); } } @@ -90,6 +89,7 @@ public bool SetRepositoryComparer(string key) { if (!_comparer.SetComparer(key)) { + _logger.LogWarning("Could not update/set the comparer key {key}.", key); return false; } diff --git a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj index ea4447da..afc540aa 100644 --- a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj +++ b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj @@ -6,6 +6,7 @@ + diff --git a/src/RepoM.Core.Plugin/SimpleInjector/IPackage.cs b/src/RepoM.Core.Plugin/SimpleInjector/IPackage.cs new file mode 100644 index 00000000..d37e9a7d --- /dev/null +++ b/src/RepoM.Core.Plugin/SimpleInjector/IPackage.cs @@ -0,0 +1,36 @@ +// Copyright (c) Simple Injector Contributors. All rights reserved. +// Licensed under the MIT License. See LICENSE file in the project root for license information. + +namespace SimpleInjector.Packaging +{ + using System.Collections.Generic; + using System.Reflection; + + /// + /// Contract for types allow registering a set of services. + /// + /// + /// The following example shows an implementation of an . + /// (); + /// container.Register(); + /// } + /// } + /// ]]> + /// The following example shows how to load all defined packages, using the + /// RegisterPackages method. + /// + /// + public interface IPackage + { + /// Registers the set of services in the specified . + /// The container the set of services is registered into. + void RegisterServices(Container container); + } +} \ No newline at end of file diff --git a/src/RepoM.Core.Plugin/SimpleInjector/PackageExtensions.cs b/src/RepoM.Core.Plugin/SimpleInjector/PackageExtensions.cs new file mode 100644 index 00000000..2e741a84 --- /dev/null +++ b/src/RepoM.Core.Plugin/SimpleInjector/PackageExtensions.cs @@ -0,0 +1,147 @@ +// Copyright (c) Simple Injector Contributors. All rights reserved. +// Licensed under the MIT License. See LICENSE file in the project root for license information. + +// This class is placed in the root namespace to allow users to start using these extension methods after +// adding the assembly reference, without find and add the correct namespace. +namespace SimpleInjector +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Globalization; + using System.Linq; + using System.Reflection; + using SimpleInjector.Packaging; + + /// + /// Extension methods for working with packages. + /// + public static class PackageExtensions + { + /// + /// Loads all implementations from the given set of + /// and calls their Register method. + /// Note that only publicly exposed classes that contain a public default constructor will be loaded. + /// + /// The container to which the packages will be applied to. + /// The assemblies that will be searched for packages. + /// Thrown when the is a null + /// reference. + public static void RegisterPackages(this Container container, IEnumerable assemblies) + { + if (container is null) + { + throw new ArgumentNullException(nameof(container)); + } + + if (assemblies is null) + { + throw new ArgumentNullException(nameof(assemblies)); + } + + foreach (var package in container.GetPackagesToRegister(assemblies)) + { + package.RegisterServices(container); + } + } + + /// + /// Loads all implementations from the given set of + /// and returns a list of created package instances. + /// + /// The container. + /// The assemblies that will be searched for packages. + /// Returns a list of created packages. + public static IPackage[] GetPackagesToRegister( + this Container container, IEnumerable assemblies) + { + if (container is null) + { + throw new ArgumentNullException(nameof(container)); + } + + if (assemblies is null) + { + throw new ArgumentNullException(nameof(assemblies)); + } + + assemblies = assemblies.ToArray(); + + if (assemblies.Any(a => a is null)) + { + throw new ArgumentNullException( + "The elements of the supplied collection should not be null.", + nameof(assemblies)); + } + + var packageTypes = ( + from assembly in assemblies + from type in GetExportedTypesFrom(assembly) + where typeof(IPackage).Info().IsAssignableFrom(type.Info()) + where !type.Info().IsAbstract + where !type.Info().IsGenericTypeDefinition + select type) + .ToArray(); + + RequiresPackageTypesHaveDefaultConstructor(packageTypes); + + return packageTypes.Select(CreatePackage).ToArray(); + } + + private static IEnumerable GetExportedTypesFrom(Assembly assembly) + { + try + { + return assembly.DefinedTypes.Select(info => info.AsType()); + } + catch (NotSupportedException) + { + // A type load exception would typically happen on an Anonymously Hosted DynamicMethods + // Assembly and it would be safe to skip this exception. + return Enumerable.Empty(); + } + } + + private static void RequiresPackageTypesHaveDefaultConstructor(Type[] packageTypes) + { + var invalidPackageType = + packageTypes.FirstOrDefault(type => !type.HasDefaultConstructor()); + + if (invalidPackageType != null) + { + throw new InvalidOperationException( + string.Format( + CultureInfo.InvariantCulture, + "The type {0} does not contain a default (public parameterless) constructor. " + + "Packages must have a default constructor.", + invalidPackageType.FullName)); + } + } + + private static IPackage CreatePackage(Type packageType) + { + try + { + return (IPackage)Activator.CreateInstance(packageType); + } + catch (Exception ex) + { + string message = string.Format( + CultureInfo.InvariantCulture, + "The creation of package type {0} failed. {1}", + packageType.FullName, + ex.Message); + + throw new InvalidOperationException(message, ex); + } + } + + private static bool HasDefaultConstructor(this Type type) => + type.GetConstructors().Any(ctor => !ctor.GetParameters().Any()); + + private static ConstructorInfo[] GetConstructors(this Type type) => + type.GetTypeInfo().DeclaredConstructors.ToArray(); + + private static TypeInfo Info(this Type type) => type.GetTypeInfo(); + } +} \ No newline at end of file diff --git a/src/RepoM.Plugin.AzureDevOps/AzureDevOpsPackage.cs b/src/RepoM.Plugin.AzureDevOps/AzureDevOpsPackage.cs index aa48fafc..71a91a30 100644 --- a/src/RepoM.Plugin.AzureDevOps/AzureDevOpsPackage.cs +++ b/src/RepoM.Plugin.AzureDevOps/AzureDevOpsPackage.cs @@ -1,5 +1,6 @@ namespace RepoM.Plugin.AzureDevOps; +using System; using JetBrains.Annotations; using RepoM.Api.IO.ModuleBasedRepositoryActionProvider; using RepoM.Core.Plugin; diff --git a/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj b/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj index 4c377057..2275e107 100644 --- a/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj +++ b/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj @@ -7,8 +7,6 @@ - - diff --git a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj index 83162336..65148b3d 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj +++ b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj @@ -6,8 +6,6 @@ - - diff --git a/src/RepoM.Plugin.LuceneSearch/RepoM.Plugin.LuceneSearch.csproj b/src/RepoM.Plugin.LuceneSearch/RepoM.Plugin.LuceneSearch.csproj index b97792b9..66895739 100644 --- a/src/RepoM.Plugin.LuceneSearch/RepoM.Plugin.LuceneSearch.csproj +++ b/src/RepoM.Plugin.LuceneSearch/RepoM.Plugin.LuceneSearch.csproj @@ -16,8 +16,6 @@ - - diff --git a/src/RepoM.Plugin.SonarCloud/RepoM.Plugin.SonarCloud.csproj b/src/RepoM.Plugin.SonarCloud/RepoM.Plugin.SonarCloud.csproj index c6041191..49196294 100644 --- a/src/RepoM.Plugin.SonarCloud/RepoM.Plugin.SonarCloud.csproj +++ b/src/RepoM.Plugin.SonarCloud/RepoM.Plugin.SonarCloud.csproj @@ -7,8 +7,6 @@ - - diff --git a/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj index e4aa1a55..1cefe858 100644 --- a/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj +++ b/src/RepoM.Plugin.Statistics/RepoM.Plugin.Statistics.csproj @@ -6,9 +6,7 @@ - - - + diff --git a/src/RepoM.Plugin.WindowsExplorerGitInfo/RepoM.Plugin.WindowsExplorerGitInfo.csproj b/src/RepoM.Plugin.WindowsExplorerGitInfo/RepoM.Plugin.WindowsExplorerGitInfo.csproj index 4e5189bc..7eb86a9e 100644 --- a/src/RepoM.Plugin.WindowsExplorerGitInfo/RepoM.Plugin.WindowsExplorerGitInfo.csproj +++ b/src/RepoM.Plugin.WindowsExplorerGitInfo/RepoM.Plugin.WindowsExplorerGitInfo.csproj @@ -7,8 +7,6 @@ - - From bfb8d235ea6461e14b3709f7ffabf69a99793264 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Thu, 8 Dec 2022 22:16:03 +0100 Subject: [PATCH 50/60] updating packages --- src/RepoM.Api/RepoM.Api.csproj | 2 +- src/RepoM.App/RepoM.App.csproj | 2 +- tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj | 2 +- .../RepoM.Plugin.AzureDevOps.Tests.csproj | 7 ++----- .../RepoM.Plugin.SonarCloud.Tests.csproj | 2 +- .../RepoM.Plugin.Statistics.Tests.csproj | 2 +- tests/Specs/Specs.csproj | 4 ++-- tests/Tests/Tests.csproj | 4 ++-- 8 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/RepoM.Api/RepoM.Api.csproj b/src/RepoM.Api/RepoM.Api.csproj index 00dd3765..f0f03682 100644 --- a/src/RepoM.Api/RepoM.Api.csproj +++ b/src/RepoM.Api/RepoM.Api.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/RepoM.App/RepoM.App.csproj b/src/RepoM.App/RepoM.App.csproj index 4cdc8ee8..3d730d57 100644 --- a/src/RepoM.App/RepoM.App.csproj +++ b/src/RepoM.App/RepoM.App.csproj @@ -37,7 +37,7 @@ - + diff --git a/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj b/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj index 41560e25..ba0c7990 100644 --- a/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj +++ b/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj @@ -19,7 +19,7 @@ - + diff --git a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj index 2780ae94..21425924 100644 --- a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj +++ b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj @@ -20,7 +20,7 @@ - + @@ -29,6 +29,7 @@ + @@ -36,8 +37,4 @@ - - - - diff --git a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj index 754785ec..008839fc 100644 --- a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj +++ b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj @@ -20,7 +20,7 @@ - + diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj index 06485762..bbe5c672 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj +++ b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj @@ -20,7 +20,7 @@ - + diff --git a/tests/Specs/Specs.csproj b/tests/Specs/Specs.csproj index bdced93d..b8e1ebd4 100644 --- a/tests/Specs/Specs.csproj +++ b/tests/Specs/Specs.csproj @@ -17,10 +17,10 @@ - + - + diff --git a/tests/Tests/Tests.csproj b/tests/Tests/Tests.csproj index 7ed92447..b4424e79 100644 --- a/tests/Tests/Tests.csproj +++ b/tests/Tests/Tests.csproj @@ -18,9 +18,9 @@ - + - + From 21f4b1709045a9b53d1cb842f56beaf484e856ae Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Thu, 8 Dec 2022 22:23:03 +0100 Subject: [PATCH 51/60] targeting net6 --- src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs | 8 ++++---- src/RepoM.Api/RepoM.Api.csproj | 2 +- src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs b/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs index d393c70b..d3c50617 100644 --- a/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs +++ b/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs @@ -71,23 +71,23 @@ private void FetchNext(object timerState) // 2. makes sure that no repository is jumped over because the list // of repositories is constantly changed and not sorted in any way in memory. // So we cannot guarantuee that each repository is fetched on each iteration if we do not sort. - var repositories = RepositoryInformationAggregator.Repositories + var repositories = RepositoryInformationAggregator.Repositories? .OrderBy(r => r.Name) - .ToList(); + .ToArray() ?? Array.Empty(); // temporarily disable the timer to prevent parallel fetch executions UpdateBehavior(AutoFetchMode.Off); _lastFetchRepository++; - if (repositories.Count <= _lastFetchRepository) + if (repositories.Length <= _lastFetchRepository) { _lastFetchRepository = 0; } RepositoryViewModel repositoryViewModel = repositories[_lastFetchRepository]; - Console.WriteLine($"Auto-fetching {repositoryViewModel.Name} (index {_lastFetchRepository} of {repositories.Count})"); + Console.WriteLine($"Auto-fetching {repositoryViewModel.Name} (index {_lastFetchRepository} of {repositories.Length})"); repositoryViewModel.IsSynchronizing = true; try diff --git a/src/RepoM.Api/RepoM.Api.csproj b/src/RepoM.Api/RepoM.Api.csproj index f0f03682..18645bb9 100644 --- a/src/RepoM.Api/RepoM.Api.csproj +++ b/src/RepoM.Api/RepoM.Api.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + net6.0 diff --git a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj index afc540aa..10c4f550 100644 --- a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj +++ b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net6.0 From 0f7784a32d053bb7cb9d5daea08f5220e3a366b3 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 9 Dec 2022 16:34:39 +0100 Subject: [PATCH 52/60] Update packages --- .../Git/AutoFetch/DefaultAutoFetchHandler.cs | 12 ++++++------ src/RepoM.Api/Git/Repository.cs | 2 +- src/RepoM.Api/Ordering/Az/AzComparer.cs | 6 +++--- .../Ordering/Composition/CompositionComparer.cs | 6 +++--- src/RepoM.Api/RepoM.Api.csproj | 4 ++-- src/RepoM.App/RepoM.App.csproj | 2 +- src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj | 2 +- tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj | 4 ++-- .../RepoM.Plugin.AzureDevOps.Tests.csproj | 4 ++-- .../RepoM.Plugin.SonarCloud.Tests.csproj | 4 ++-- .../RepoM.Plugin.Statistics.Tests.csproj | 4 ++-- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs b/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs index d3c50617..44b0f6f3 100644 --- a/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs +++ b/src/RepoM.Api/Git/AutoFetch/DefaultAutoFetchHandler.cs @@ -9,7 +9,7 @@ namespace RepoM.Api.Git.AutoFetch; public class DefaultAutoFetchHandler : IAutoFetchHandler { private bool _active; - private AutoFetchMode? _mode = null; + private AutoFetchMode? _mode; private readonly Timer _timer; private readonly Dictionary _profiles; private int _lastFetchRepository = -1; @@ -26,10 +26,10 @@ public DefaultAutoFetchHandler( _profiles = new Dictionary { - { AutoFetchMode.Off, new AutoFetchProfile() { PauseBetweenFetches = TimeSpan.MaxValue, } }, - { AutoFetchMode.Discretely, new AutoFetchProfile() { PauseBetweenFetches = TimeSpan.FromMinutes(5), } }, - { AutoFetchMode.Adequate, new AutoFetchProfile() { PauseBetweenFetches = TimeSpan.FromMinutes(1), } }, - { AutoFetchMode.Aggressive, new AutoFetchProfile() { PauseBetweenFetches = TimeSpan.FromSeconds(2), } }, + { AutoFetchMode.Off, new AutoFetchProfile { PauseBetweenFetches = TimeSpan.MaxValue, } }, + { AutoFetchMode.Discretely, new AutoFetchProfile { PauseBetweenFetches = TimeSpan.FromMinutes(5), } }, + { AutoFetchMode.Adequate, new AutoFetchProfile { PauseBetweenFetches = TimeSpan.FromMinutes(1), } }, + { AutoFetchMode.Aggressive, new AutoFetchProfile { PauseBetweenFetches = TimeSpan.FromSeconds(2), } }, }; _timer = new Timer(FetchNext, null, Timeout.Infinite, Timeout.Infinite); @@ -134,7 +134,7 @@ public AutoFetchMode Mode } _mode = value; - Console.WriteLine("Auto fetch is: " + _mode.GetValueOrDefault().ToString()); + Console.WriteLine("Auto fetch is: " + _mode.GetValueOrDefault()); UpdateBehavior(); } diff --git a/src/RepoM.Api/Git/Repository.cs b/src/RepoM.Api/Git/Repository.cs index fc3352b2..7ba85cc2 100644 --- a/src/RepoM.Api/Git/Repository.cs +++ b/src/RepoM.Api/Git/Repository.cs @@ -18,7 +18,7 @@ public Repository() Location = string.Empty; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not Repository other) { diff --git a/src/RepoM.Api/Ordering/Az/AzComparer.cs b/src/RepoM.Api/Ordering/Az/AzComparer.cs index 007bb648..5b667c86 100644 --- a/src/RepoM.Api/Ordering/Az/AzComparer.cs +++ b/src/RepoM.Api/Ordering/Az/AzComparer.cs @@ -15,19 +15,19 @@ public AzComparer(int weight, string? property) _property = property; } - public int Compare(IRepository x, IRepository y) + public int Compare(IRepository? x, IRepository? y) { if (ReferenceEquals(x, y)) { return 0; } - if (ReferenceEquals(null, y)) + if (y is null) { return _weight; } - if (ReferenceEquals(null, x)) + if (x is null) { return -1 * _weight; } diff --git a/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs b/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs index 3c15f40d..274b2669 100644 --- a/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs +++ b/src/RepoM.Api/Ordering/Composition/CompositionComparer.cs @@ -14,19 +14,19 @@ public CompositionComparer(IEnumerable comparers) _comparers = comparers.ToArray(); } - public int Compare(IRepository x, IRepository y) + public int Compare(IRepository? x, IRepository? y) { if (ReferenceEquals(x, y)) { return 0; } - if (ReferenceEquals(null, y)) + if (y is null) { return 1; } - if (ReferenceEquals(null, x)) + if (x is null) { return -1; } diff --git a/src/RepoM.Api/RepoM.Api.csproj b/src/RepoM.Api/RepoM.Api.csproj index 18645bb9..66a0e4e1 100644 --- a/src/RepoM.Api/RepoM.Api.csproj +++ b/src/RepoM.Api/RepoM.Api.csproj @@ -8,9 +8,9 @@ - + - + diff --git a/src/RepoM.App/RepoM.App.csproj b/src/RepoM.App/RepoM.App.csproj index 3d730d57..77e2fa9b 100644 --- a/src/RepoM.App/RepoM.App.csproj +++ b/src/RepoM.App/RepoM.App.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj index 10c4f550..dd45f053 100644 --- a/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj +++ b/src/RepoM.Core.Plugin/RepoM.Core.Plugin.csproj @@ -7,7 +7,7 @@ - + diff --git a/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj b/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj index ba0c7990..81dd4062 100644 --- a/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj +++ b/tests/RepoM.Api.Tests/RepoM.Api.Tests.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj index 21425924..b657a087 100644 --- a/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj +++ b/tests/RepoM.Plugin.AzureDevOps.Tests/RepoM.Plugin.AzureDevOps.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj index 008839fc..2c3ff56c 100644 --- a/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj +++ b/tests/RepoM.Plugin.SonarCloud.Tests/RepoM.Plugin.SonarCloud.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj index bbe5c672..7fc42ff0 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj +++ b/tests/RepoM.Plugin.Statistics.Tests/RepoM.Plugin.Statistics.Tests.csproj @@ -18,8 +18,8 @@ - - + + From fe9eb56c61d5b8981ccd115a578e026b8c1f660c Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 9 Dec 2022 16:42:29 +0100 Subject: [PATCH 53/60] Remove data after 30 days. --- .../StatisticsModule.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/RepoM.Plugin.Statistics/StatisticsModule.cs b/src/RepoM.Plugin.Statistics/StatisticsModule.cs index 5111d51c..21f342cb 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsModule.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsModule.cs @@ -25,6 +25,7 @@ internal class StatisticsModule : IModule private string _basePath = string.Empty; private IDisposable? _disposable; private readonly JsonSerializerSettings _settings; + private Task _task; public StatisticsModule( StatisticsService service, @@ -54,6 +55,8 @@ public async Task StartAsync() _disposable = WriteEventsToFile(); await ProcessEventsFromFile().ConfigureAwait(false); + + _task = Task.Run(RemoveOldFilesAsync); } public Task StopAsync() @@ -62,6 +65,45 @@ public Task StopAsync() return Task.CompletedTask; } + private async Task RemoveOldFilesAsync() + { + if (!_fileSystem.Directory.Exists(_basePath)) + { + return; + } + + IOrderedEnumerable orderedEnumerable = _fileSystem.Directory.GetFiles(_basePath, "statistics.v1.*.json").OrderBy(f => f); + + DateTime threshold = _clock.Now.AddDays(-30); + + foreach (var file in orderedEnumerable) + { + IEvent[] list = Array.Empty(); + + try + { + var json = await _fileSystem.File.ReadAllTextAsync(file, CancellationToken.None).ConfigureAwait(false); + list = JsonConvert.DeserializeObject(json, _settings) ?? Array.Empty(); + } + catch (Exception e) + { + _logger.LogError(e, "Could not read or deserialize data from '{filename}'. {message}", file, e.Message); + } + + if (list.All(item => item.Timestamp <= threshold)) + { + try + { + _fileSystem.File.Delete(file); + } + catch (Exception e) + { + _logger.LogError(e, "Could not delete '{filename}'. {message}", file, e.Message); + } + } + } + } + private async Task ProcessEventsFromFile() { if (!_fileSystem.Directory.Exists(_basePath)) From 073ae91ab0ba08a0226ae15f484bca2335b321a8 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 9 Dec 2022 16:43:16 +0100 Subject: [PATCH 54/60] . --- src/RepoM.Plugin.Statistics/StatisticsModule.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/RepoM.Plugin.Statistics/StatisticsModule.cs b/src/RepoM.Plugin.Statistics/StatisticsModule.cs index 21f342cb..d61b6c12 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsModule.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsModule.cs @@ -25,7 +25,6 @@ internal class StatisticsModule : IModule private string _basePath = string.Empty; private IDisposable? _disposable; private readonly JsonSerializerSettings _settings; - private Task _task; public StatisticsModule( StatisticsService service, @@ -56,7 +55,7 @@ public async Task StartAsync() await ProcessEventsFromFile().ConfigureAwait(false); - _task = Task.Run(RemoveOldFilesAsync); + _ = Task.Run(RemoveOldFilesAsync); } public Task StopAsync() From 3de459a7a3b56aa8a4079d3ff561b86f5c2993fe Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 9 Dec 2022 16:44:51 +0100 Subject: [PATCH 55/60] .. --- src/RepoM.Plugin.Statistics/StatisticsModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/RepoM.Plugin.Statistics/StatisticsModule.cs b/src/RepoM.Plugin.Statistics/StatisticsModule.cs index d61b6c12..e95b8a9b 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsModule.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsModule.cs @@ -93,6 +93,7 @@ private async Task RemoveOldFilesAsync() { try { + _logger.LogDebug("Remove old Statistics file '{filename}'", file); _fileSystem.File.Delete(file); } catch (Exception e) From 159942b29249f4803a505b5aa5f7ee4e74e53920 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Sat, 10 Dec 2022 22:28:34 +0100 Subject: [PATCH 56/60] wip --- src/RepoM.Api/RepoM.Api.csproj | 1 + .../RepoM.Plugin.AzureDevOps.csproj | 2 ++ .../IReadOnlyRepositoryStatistics.cs | 10 ++++++++++ .../Ordering/UsageScoreCalculator.cs | 20 ++++++++++++++++--- .../Ordering/UsageScorerFactory.cs | 7 +++++-- .../RepositoryStatistics.cs | 18 ++++++++++++++++- .../StatisticsService.cs | 7 +++++++ .../Ordering/UsageScorerFactoryTest.cs | 6 ++++-- 8 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 src/RepoM.Plugin.Statistics/IReadOnlyRepositoryStatistics.cs diff --git a/src/RepoM.Api/RepoM.Api.csproj b/src/RepoM.Api/RepoM.Api.csproj index 66a0e4e1..610b798c 100644 --- a/src/RepoM.Api/RepoM.Api.csproj +++ b/src/RepoM.Api/RepoM.Api.csproj @@ -5,6 +5,7 @@ + diff --git a/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj b/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj index 2275e107..06954750 100644 --- a/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj +++ b/src/RepoM.Plugin.AzureDevOps/RepoM.Plugin.AzureDevOps.csproj @@ -7,6 +7,8 @@ + + diff --git a/src/RepoM.Plugin.Statistics/IReadOnlyRepositoryStatistics.cs b/src/RepoM.Plugin.Statistics/IReadOnlyRepositoryStatistics.cs new file mode 100644 index 00000000..bca28754 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/IReadOnlyRepositoryStatistics.cs @@ -0,0 +1,10 @@ +namespace RepoM.Plugin.Statistics; + +using System; + +internal interface IReadOnlyRepositoryStatistics +{ + int GetRecordingCount(DateTime from, DateTime to); + int GetRecordingCountFrom(DateTime from); + int GetRecordingCountBefore(DateTime to); +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs index c0ec962d..759e8497 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs @@ -2,21 +2,35 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; using System.Collections.Generic; +using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; internal class UsageScoreCalculator : IRepositoryScoreCalculator { private readonly StatisticsService _service; + private readonly IClock _clock; - public UsageScoreCalculator(StatisticsService service) + public UsageScoreCalculator(StatisticsService service, IClock clock) { _service = service ?? throw new ArgumentNullException(nameof(service)); + _clock = clock ?? throw new ArgumentNullException(nameof(clock)); } public int Score(IRepository repository) { - IReadOnlyList recordings = _service.GetRecordings(repository); - return recordings.Count; + var now = _clock.Now; + + IReadOnlyRepositoryStatistics? repositoryRecording = _service.GetRepositoryRecording(repository); + if (repositoryRecording == null) + { + return 0; + } + + var count = repositoryRecording.GetRecordingCount(now.AddDays(5), now); + return count; + + // IReadOnlyList recordings = _service.GetRecordings(repository); + // return recordings.Count; } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs index 5fe60a6d..a28df200 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs @@ -1,19 +1,22 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; +using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.RepositoryOrdering; public sealed class UsageScorerFactory : IRepositoryScoreCalculatorFactory { private readonly StatisticsService _service; + private readonly IClock _clock; - public UsageScorerFactory(StatisticsService service) + public UsageScorerFactory(StatisticsService service, IClock clock) { _service = service ?? throw new ArgumentNullException(nameof(service)); + _clock = clock ?? throw new ArgumentNullException(nameof(clock)); } public IRepositoryScoreCalculator Create(UsageScorerConfigurationV1 config) { - return new UsageScoreCalculator(_service); + return new UsageScoreCalculator(_service, _clock); } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs b/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs index 26e11a64..f59a17d8 100644 --- a/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs +++ b/src/RepoM.Plugin.Statistics/RepositoryStatistics.cs @@ -2,10 +2,11 @@ namespace RepoM.Plugin.Statistics; using System; using System.Collections.Generic; +using System.Linq; using RepoM.Core.Plugin.Common; using RepoM.Plugin.Statistics.Interface; -internal class RepositoryStatistics +internal class RepositoryStatistics : IReadOnlyRepositoryStatistics { private readonly string _repositoryPath; private readonly IClock _clock; @@ -31,6 +32,21 @@ public IEvent Record() return evt; } + int IReadOnlyRepositoryStatistics.GetRecordingCount(DateTime from, DateTime to) + { + return Recordings.Count(recordingDate => recordingDate < to && recordingDate >= from); + } + + int IReadOnlyRepositoryStatistics.GetRecordingCountFrom(DateTime from) + { + return Recordings.Count(recordingDate => recordingDate >= from); + } + + int IReadOnlyRepositoryStatistics.GetRecordingCountBefore(DateTime to) + { + return Recordings.Count(recordingDate => recordingDate < to); + } + public void Apply(IEvent evt) { if (evt is RepositoryActionRecordedEvent repositoryActionRecordedEvent) diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs index 31dbfd1f..67497c36 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsService.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -43,6 +43,13 @@ public IReadOnlyList GetRepositories() return _recordings.Select(x => x.Key).ToImmutableArray(); } + internal IReadOnlyRepositoryStatistics? GetRepositoryRecording(IRepository repository) + { + return !_recordings.TryGetValue(repository.SafePath, out RepositoryStatistics? repositoryStatistics) + ? null + : repositoryStatistics; + } + public IReadOnlyList GetRecordings(IRepository repository) { if (_recordings.TryGetValue(repository.SafePath, out RepositoryStatistics? repositoryStatistics)) diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs index 66cb936c..4017cc01 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs @@ -10,17 +10,19 @@ namespace RepoM.Plugin.Statistics.Tests.Ordering; public class UsageScorerFactoryTest { private readonly StatisticsService _service; + private readonly IClock _clock; public UsageScorerFactoryTest() { - _service = new StatisticsService(A.Fake()); + _clock = A.Fake(); + _service = new StatisticsService(_clock); } [Fact] public void Create_ShouldReturnInstanceOfUsageScoreCalculator() { // arrange - var sut = new UsageScorerFactory(_service); + var sut = new UsageScorerFactory(_service, _clock); var config = new UsageScorerConfigurationV1(); // act From a9b06505a8619759d321a1fb24427fd1d7cf38e8 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 12 Dec 2022 20:45:42 +0100 Subject: [PATCH 57/60] Wip --- .../Ordering/UsageScoreCalculator.cs | 113 +++++++++++++++++- .../Ordering/UsageScorerConfigurationV1.cs | 15 ++- .../Ordering/UsageScorerFactory.cs | 26 +++- .../StatisticsService.cs | 6 +- .../Ordering/UsageScorerFactoryTest.cs | 3 +- 5 files changed, 148 insertions(+), 15 deletions(-) diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs index 759e8497..f4dd9f49 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs @@ -2,35 +2,136 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Logging; using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; +internal class RangeConfig +{ + public TimeSpan MaxAge { get; set; } + + public int Score { get; set;} + + public int MaxItems { get; set; } = int.MaxValue; +} + +internal class ScoreCalculatorConfig +{ + public List Ranges { get; set; } = new List(); + + public int MaxScore { get; set; } = int.MaxValue; +} + internal class UsageScoreCalculator : IRepositoryScoreCalculator { private readonly StatisticsService _service; private readonly IClock _clock; + private readonly ScoreCalculatorConfig _config; + private readonly ILogger _logger; + private readonly List _ranges; - public UsageScoreCalculator(StatisticsService service, IClock clock) + public UsageScoreCalculator(StatisticsService service, IClock clock, ScoreCalculatorConfig config, ILogger logger) { _service = service ?? throw new ArgumentNullException(nameof(service)); _clock = clock ?? throw new ArgumentNullException(nameof(clock)); + _config = config ?? throw new ArgumentNullException(nameof(config)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _ranges = config.Ranges.OrderBy(x => x.MaxAge).ToList(); } public int Score(IRepository repository) { - var now = _clock.Now; + try + { + return Score1(repository); + } + catch (Exception e) + { + _logger.LogError(e, "------------------- ERROR {m}", e.Message); + return 0; + } + } + + public int Score1(IRepository repository) + { + DateTime now = _clock.Now; + _logger.LogDebug("-- {Repository}", repository.SafePath); IReadOnlyRepositoryStatistics? repositoryRecording = _service.GetRepositoryRecording(repository); if (repositoryRecording == null) { return 0; } + + var score = 0; + + // first one + var unused = 0; + + var previousRange = _ranges[0]; + var currentRange = _ranges[0]; + DateTime dateTime = now.Subtract(currentRange.MaxAge); + _logger.LogDebug("Age: {age}", currentRange.MaxAge); + _logger.LogDebug("Date: {dt}", dateTime); + var count1 = repositoryRecording.GetRecordingCountFrom(dateTime); + if (count1 <= currentRange.MaxItems) + { + score += count1 * currentRange.Score; + } + else + { + score += currentRange.MaxItems * currentRange.Score; + unused = count1 - currentRange.MaxItems; + } + + _logger.LogDebug("-- {count} - {score} - {unused}", count1, score, unused); + + for (int i = 1; i < _ranges.Count; i++) + { + currentRange = _ranges[i]; + var c = repositoryRecording.GetRecordingCount( + now.Subtract(previousRange.MaxAge), + now.Subtract(currentRange.MaxAge)) + unused; + + if (c <= currentRange.MaxItems) + { + score += c * currentRange.Score; + } + else + { + score += currentRange.MaxItems * currentRange.Score; + unused = c - currentRange.MaxItems; + } + _logger.LogDebug("-- {count} - {score} - {unused}", c, score, unused); + previousRange = currentRange; + } + + currentRange = _ranges.Last(); + var countLast = repositoryRecording.GetRecordingCountBefore(now.Add(-1 * currentRange.MaxAge)) + unused; + if (countLast <= currentRange.MaxItems) + { + score += countLast * currentRange.Score; + } + else + { + score += currentRange.MaxItems * currentRange.Score; + unused = countLast - currentRange.MaxItems; + } + + _logger.LogDebug("-- {count} - {score} - {unused} [max {max}]", countLast, score, unused, _config.MaxScore); + + if (score < 0) + { + return 0; + } - var count = repositoryRecording.GetRecordingCount(now.AddDays(5), now); - return count; + if (score > _config.MaxScore) + { + return _config.MaxScore; + } - // IReadOnlyList recordings = _service.GetRecordings(repository); - // return recordings.Count; + return score; } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs index 6511747a..92cedc4b 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerConfigurationV1.cs @@ -1,12 +1,21 @@ namespace RepoM.Plugin.Statistics.Ordering; +using System; +using System.Collections.Generic; using RepoM.Core.Plugin.RepositoryOrdering.Configuration; public sealed class UsageScorerConfigurationV1 : IRepositoryScorerConfiguration { - public UsageScorerConfigurationV1() - { - } + public List Windows { get; set; } = new List(); + + public int? MaxScore { get; set; } = null; +} + +public sealed class Windows +{ + public TimeSpan Until { get; set; } public int Weight { get; set; } + + public int MaxItems { get; set; } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs index a28df200..b417b6b1 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs @@ -1,6 +1,8 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; +using System.Linq; +using Microsoft.Extensions.Logging; using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.RepositoryOrdering; @@ -8,15 +10,35 @@ public sealed class UsageScorerFactory : IRepositoryScoreCalculatorFactory new RangeConfig + { + Score = x.Weight, + MaxItems = x.MaxItems, + MaxAge = x.Until, + }) + .ToList(), + }; + + + return new UsageScoreCalculator( + _service, + _clock, + scoreCalculatorConfig, + _loggerFactory.CreateLogger(typeof(UsageScoreCalculator))); } } \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/StatisticsService.cs b/src/RepoM.Plugin.Statistics/StatisticsService.cs index 67497c36..437f3a9a 100644 --- a/src/RepoM.Plugin.Statistics/StatisticsService.cs +++ b/src/RepoM.Plugin.Statistics/StatisticsService.cs @@ -45,9 +45,9 @@ public IReadOnlyList GetRepositories() internal IReadOnlyRepositoryStatistics? GetRepositoryRecording(IRepository repository) { - return !_recordings.TryGetValue(repository.SafePath, out RepositoryStatistics? repositoryStatistics) - ? null - : repositoryStatistics; + return _recordings.TryGetValue(repository.SafePath, out RepositoryStatistics? repositoryStatistics) + ? repositoryStatistics + : null; } public IReadOnlyList GetRecordings(IRepository repository) diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs index 4017cc01..fe2c96fd 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs @@ -2,6 +2,7 @@ namespace RepoM.Plugin.Statistics.Tests.Ordering; using FakeItEasy; using FluentAssertions; +using Microsoft.Extensions.Logging.Abstractions; using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Plugin.Statistics.Ordering; @@ -22,7 +23,7 @@ public UsageScorerFactoryTest() public void Create_ShouldReturnInstanceOfUsageScoreCalculator() { // arrange - var sut = new UsageScorerFactory(_service, _clock); + var sut = new UsageScorerFactory(_service, _clock, new NullLoggerFactory()); var config = new UsageScorerConfigurationV1(); // act From fee1420f429eeca891c0f3b49778b646d17d976f Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 12 Dec 2022 21:41:05 +0100 Subject: [PATCH 58/60] add tests --- .../Ordering/UsageScoreCalculator.cs | 96 +++++------ .../Ordering/UsageScorerFactory.cs | 7 +- .../Ordering/UsageScoreCalculatorTest.cs | 155 ++++++++++++++++++ .../Ordering/UsageScorerFactoryTest.cs | 3 +- 4 files changed, 199 insertions(+), 62 deletions(-) create mode 100644 tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScoreCalculatorTest.cs diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs index f4dd9f49..efde26a4 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs @@ -19,7 +19,7 @@ internal class RangeConfig internal class ScoreCalculatorConfig { - public List Ranges { get; set; } = new List(); + public List Ranges { get; set; } = new(); public int MaxScore { get; set; } = int.MaxValue; } @@ -29,35 +29,29 @@ internal class UsageScoreCalculator : IRepositoryScoreCalculator private readonly StatisticsService _service; private readonly IClock _clock; private readonly ScoreCalculatorConfig _config; - private readonly ILogger _logger; private readonly List _ranges; - public UsageScoreCalculator(StatisticsService service, IClock clock, ScoreCalculatorConfig config, ILogger logger) + public UsageScoreCalculator(StatisticsService service, IClock clock, ScoreCalculatorConfig config) { _service = service ?? throw new ArgumentNullException(nameof(service)); _clock = clock ?? throw new ArgumentNullException(nameof(clock)); _config = config ?? throw new ArgumentNullException(nameof(config)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _ranges = config.Ranges.OrderBy(x => x.MaxAge).ToList(); } public int Score(IRepository repository) { - try + if (_ranges.Count == 0) { - return Score1(repository); + return 0; } - catch (Exception e) + + if (_config.MaxScore == 0) { - _logger.LogError(e, "------------------- ERROR {m}", e.Message); return 0; } - } - public int Score1(IRepository repository) - { DateTime now = _clock.Now; - _logger.LogDebug("-- {Repository}", repository.SafePath); IReadOnlyRepositoryStatistics? repositoryRecording = _service.GetRepositoryRecording(repository); if (repositoryRecording == null) @@ -65,71 +59,63 @@ public int Score1(IRepository repository) return 0; } - var score = 0; + var score = CalculateScore(now, repositoryRecording); + + if (score < 0) + { + return 0; + } + + if (score > _config.MaxScore) + { + return _config.MaxScore; + } + + return score; + } - // first one - var unused = 0; + private int CalculateScore(DateTime now, IReadOnlyRepositoryStatistics repositoryRecording) + { + int score = 0; + int unused = 0; + int currentCount = 0; var previousRange = _ranges[0]; var currentRange = _ranges[0]; + DateTime dateTime = now.Subtract(currentRange.MaxAge); - _logger.LogDebug("Age: {age}", currentRange.MaxAge); - _logger.LogDebug("Date: {dt}", dateTime); - var count1 = repositoryRecording.GetRecordingCountFrom(dateTime); - if (count1 <= currentRange.MaxItems) + + currentCount = repositoryRecording.GetRecordingCountFrom(dateTime); + if (currentCount <= currentRange.MaxItems) { - score += count1 * currentRange.Score; + score += currentCount * currentRange.Score; + unused = 0; } else { score += currentRange.MaxItems * currentRange.Score; - unused = count1 - currentRange.MaxItems; + unused = currentCount - currentRange.MaxItems; } - _logger.LogDebug("-- {count} - {score} - {unused}", count1, score, unused); - - for (int i = 1; i < _ranges.Count; i++) + for (var i = 1; i < _ranges.Count; i++) { currentRange = _ranges[i]; - var c = repositoryRecording.GetRecordingCount( - now.Subtract(previousRange.MaxAge), - now.Subtract(currentRange.MaxAge)) + unused; + currentCount = repositoryRecording.GetRecordingCount( + now.Subtract(currentRange.MaxAge), + now.Subtract(previousRange.MaxAge)) + unused; - if (c <= currentRange.MaxItems) + if (currentCount <= currentRange.MaxItems) { - score += c * currentRange.Score; + score += currentCount * currentRange.Score; + unused = 0; } else { score += currentRange.MaxItems * currentRange.Score; - unused = c - currentRange.MaxItems; + unused = currentCount - currentRange.MaxItems; } - _logger.LogDebug("-- {count} - {score} - {unused}", c, score, unused); - previousRange = currentRange; - } - - currentRange = _ranges.Last(); - var countLast = repositoryRecording.GetRecordingCountBefore(now.Add(-1 * currentRange.MaxAge)) + unused; - if (countLast <= currentRange.MaxItems) - { - score += countLast * currentRange.Score; - } - else - { - score += currentRange.MaxItems * currentRange.Score; - unused = countLast - currentRange.MaxItems; - } - _logger.LogDebug("-- {count} - {score} - {unused} [max {max}]", countLast, score, unused, _config.MaxScore); - - if (score < 0) - { - return 0; - } - - if (score > _config.MaxScore) - { - return _config.MaxScore; + previousRange = currentRange; } return score; diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs index b417b6b1..1297bfe2 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs @@ -10,13 +10,11 @@ public sealed class UsageScorerFactory : IRepositoryScoreCalculatorFactory(); + A.CallTo(() => _repository.SafePath).Returns("DummyValue"); + + _calculatorClock = A.Fake(); + IClock statisticsServiceClock = A.Fake(); + _service = new StatisticsService(statisticsServiceClock); + + var now = new DateTime(2022, 2, 3, 5, 6, 7, 8); + A.CallTo(() => _calculatorClock.Now).Returns(now); + + _defaultConfig = new ScoreCalculatorConfig + { + MaxScore = 100, + Ranges = new List + { + new() + { + Score = 3, + MaxItems = 100, + MaxAge = new TimeSpan(0, 2, 0, 0), + }, + new() + { + Score = 1, + MaxItems = 100, + MaxAge = new TimeSpan(0, 7, 0, 0), + }, + }, + }; + + A.CallTo(() => statisticsServiceClock.Now).ReturnsNextFromSequence( + now.AddHours(-1), + now.AddHours(-2), + now.AddHours(-3)); + + _service.Record(_repository); // now - 1h + _service.Record(_repository); // now - 2h + _service.Record(_repository); // now - 3h + + _sut = new UsageScoreCalculator(_service, _calculatorClock, _defaultConfig); + } + + [Fact] + public void Score_ShouldUseRecordings_WhenCalculating() + { + // arrange + + // act + var result = _sut.Score(_repository); + + // assert + result.Should().Be(7); + } + + [Fact] + public void Score_MaxCount_Scenario1() + { + // arrange + _defaultConfig.MaxScore = 0; + + // act + var result = _sut.Score(_repository); + + // assert + result.Should().Be(0); + } + + [Fact] + public void Score_MaxCount_Scenario2() + { + // arrange + _defaultConfig.MaxScore = 4; + + // act + var result = _sut.Score(_repository); + + // assert + result.Should().Be(4); + } + + [Fact] + public void Score_ShouldReturnZero_WhenNoRangesSpecified() + { + // arrange + _defaultConfig.Ranges.Clear(); + _sut = new UsageScoreCalculator(_service, _calculatorClock, _defaultConfig); + + // act + var result = _sut.Score(_repository); + + // assert + result.Should().Be(0); + } + + [Fact] + public void Score_ShouldReturnZero_RepositoryWasNotFound() + { + // arrange + IRepository r = A.Fake(); + A.CallTo(() => r.SafePath).Returns("OtherDummyValue"); + + // act + var result = _sut.Score(r); + + // assert + result.Should().Be(0); + } + + [Fact] + public void Score_Scenario1() + { + // arrange + _defaultConfig.Ranges[0].MaxItems = 1; + + // act + var result = _sut.Score(_repository); + + // assert + result.Should().Be(5); + } + + [Fact] + public void Score_Scenario2() + { + // arrange + _defaultConfig.Ranges[1].MaxItems = 0; + + // act + var result = _sut.Score(_repository); + + // assert + result.Should().Be(6); + } +} \ No newline at end of file diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs index fe2c96fd..4017cc01 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScorerFactoryTest.cs @@ -2,7 +2,6 @@ namespace RepoM.Plugin.Statistics.Tests.Ordering; using FakeItEasy; using FluentAssertions; -using Microsoft.Extensions.Logging.Abstractions; using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.RepositoryOrdering; using RepoM.Plugin.Statistics.Ordering; @@ -23,7 +22,7 @@ public UsageScorerFactoryTest() public void Create_ShouldReturnInstanceOfUsageScoreCalculator() { // arrange - var sut = new UsageScorerFactory(_service, _clock, new NullLoggerFactory()); + var sut = new UsageScorerFactory(_service, _clock); var config = new UsageScorerConfigurationV1(); // act From 6dd312f4260c27dd51bf2ed80d1468a03a11ab03 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 12 Dec 2022 21:44:36 +0100 Subject: [PATCH 59/60] .. --- .../Ordering/UsageScoreCalculator.cs | 17 ++++++++--------- .../Ordering/UsageScorerFactory.cs | 2 +- .../Ordering/UsageScoreCalculatorTest.cs | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs index efde26a4..2fac49ec 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs @@ -3,12 +3,11 @@ namespace RepoM.Plugin.Statistics.Ordering; using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Extensions.Logging; using RepoM.Core.Plugin.Common; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; -internal class RangeConfig +internal class ScoreCalculatorRangeConfig { public TimeSpan MaxAge { get; set; } @@ -19,7 +18,7 @@ internal class RangeConfig internal class ScoreCalculatorConfig { - public List Ranges { get; set; } = new(); + public List Ranges { get; set; } = new(); public int MaxScore { get; set; } = int.MaxValue; } @@ -29,7 +28,7 @@ internal class UsageScoreCalculator : IRepositoryScoreCalculator private readonly StatisticsService _service; private readonly IClock _clock; private readonly ScoreCalculatorConfig _config; - private readonly List _ranges; + private readonly List _ranges; public UsageScoreCalculator(StatisticsService service, IClock clock, ScoreCalculatorConfig config) { @@ -76,12 +75,12 @@ public int Score(IRepository repository) private int CalculateScore(DateTime now, IReadOnlyRepositoryStatistics repositoryRecording) { - int score = 0; - int unused = 0; - int currentCount = 0; + var score = 0; + var unused = 0; + var currentCount = 0; - var previousRange = _ranges[0]; - var currentRange = _ranges[0]; + ScoreCalculatorRangeConfig previousRange = _ranges[0]; + ScoreCalculatorRangeConfig currentRange = _ranges[0]; DateTime dateTime = now.Subtract(currentRange.MaxAge); diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs index 1297bfe2..0ce68224 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScorerFactory.cs @@ -23,7 +23,7 @@ public IRepositoryScoreCalculator Create(UsageScorerConfigurationV1 config) { MaxScore = config.MaxScore ?? int.MaxValue, Ranges = config.Windows - .Select(x => new RangeConfig + .Select(x => new ScoreCalculatorRangeConfig { Score = x.Weight, MaxItems = x.MaxItems, diff --git a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScoreCalculatorTest.cs b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScoreCalculatorTest.cs index 9369980a..3a8bb8cb 100644 --- a/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScoreCalculatorTest.cs +++ b/tests/RepoM.Plugin.Statistics.Tests/Ordering/UsageScoreCalculatorTest.cs @@ -32,7 +32,7 @@ public UsageScoreCalculatorTest() _defaultConfig = new ScoreCalculatorConfig { MaxScore = 100, - Ranges = new List + Ranges = new List { new() { From 0448caa1eb6a64973fd74bcda6c1d777733a4a3b Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Mon, 12 Dec 2022 21:46:16 +0100 Subject: [PATCH 60/60] Move types to own files --- .../Ordering/ScoreCalculatorConfig.cs | 10 ++++++++++ .../Ordering/ScoreCalculatorRangeConfig.cs | 12 ++++++++++++ .../Ordering/UsageScoreCalculator.cs | 16 ---------------- 3 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorConfig.cs create mode 100644 src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorRangeConfig.cs diff --git a/src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorConfig.cs b/src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorConfig.cs new file mode 100644 index 00000000..ef820e82 --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorConfig.cs @@ -0,0 +1,10 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System.Collections.Generic; + +internal class ScoreCalculatorConfig +{ + public List Ranges { get; set; } = new(); + + public int MaxScore { get; set; } = int.MaxValue; +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorRangeConfig.cs b/src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorRangeConfig.cs new file mode 100644 index 00000000..bf60631c --- /dev/null +++ b/src/RepoM.Plugin.Statistics/Ordering/ScoreCalculatorRangeConfig.cs @@ -0,0 +1,12 @@ +namespace RepoM.Plugin.Statistics.Ordering; + +using System; + +internal class ScoreCalculatorRangeConfig +{ + public TimeSpan MaxAge { get; set; } + + public int Score { get; set;} + + public int MaxItems { get; set; } = int.MaxValue; +} \ No newline at end of file diff --git a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs index 2fac49ec..fe18fe2b 100644 --- a/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs +++ b/src/RepoM.Plugin.Statistics/Ordering/UsageScoreCalculator.cs @@ -7,22 +7,6 @@ namespace RepoM.Plugin.Statistics.Ordering; using RepoM.Core.Plugin.Repository; using RepoM.Core.Plugin.RepositoryOrdering; -internal class ScoreCalculatorRangeConfig -{ - public TimeSpan MaxAge { get; set; } - - public int Score { get; set;} - - public int MaxItems { get; set; } = int.MaxValue; -} - -internal class ScoreCalculatorConfig -{ - public List Ranges { get; set; } = new(); - - public int MaxScore { get; set; } = int.MaxValue; -} - internal class UsageScoreCalculator : IRepositoryScoreCalculator { private readonly StatisticsService _service;