Skip to content

Commit 0f33728

Browse files
committed
Introduce 'remotes' to manage 'profiles'
From the beginning, `Profiles` where introduced to make it possible to choose between several source repositories. Back then, the main use case of profiles was to store the information from 'which' template a project was generated initially and to be able to update those templates when needed. `remotes` now extends this concept by making it possible to 'manage' profiles by enabling to add and remove profiles during development and changing the default profile to be used. The feature is called `remotes` as it is very close to Git's remotes. Under the hood it will stick with `Profiles` until the feature gets to a more mature state.
1 parent 25d2cc2 commit 0f33728

File tree

24 files changed

+493
-13
lines changed

24 files changed

+493
-13
lines changed

Moryx.Cli.sln

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt
2020
Directory.Build.targets = Directory.Build.targets
2121
EndProjectSection
2222
EndProject
23-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moryx.Cli.Commands.Tests", "src\Tests\Moryx.Cli.Commands.Tests\Moryx.Cli.Commands.Tests.csproj", "{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}"
23+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moryx.Cli.Commands.Tests", "src\Tests\Moryx.Cli.Commands.Tests\Moryx.Cli.Commands.Tests.csproj", "{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}"
24+
EndProject
25+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moryx.Cli.Remotes", "src\Moryx.Cli.Remotes\Moryx.Cli.Remotes.csproj", "{0C42AB23-AFA3-44B5-986C-BF7991275897}"
2426
EndProject
2527
Global
2628
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -52,6 +54,10 @@ Global
5254
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}.Debug|Any CPU.Build.0 = Debug|Any CPU
5355
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}.Release|Any CPU.ActiveCfg = Release|Any CPU
5456
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}.Release|Any CPU.Build.0 = Release|Any CPU
57+
{0C42AB23-AFA3-44B5-986C-BF7991275897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58+
{0C42AB23-AFA3-44B5-986C-BF7991275897}.Debug|Any CPU.Build.0 = Debug|Any CPU
59+
{0C42AB23-AFA3-44B5-986C-BF7991275897}.Release|Any CPU.ActiveCfg = Release|Any CPU
60+
{0C42AB23-AFA3-44B5-986C-BF7991275897}.Release|Any CPU.Build.0 = Release|Any CPU
5561
EndGlobalSection
5662
GlobalSection(SolutionProperties) = preSolution
5763
HideSolutionNode = FALSE

src/Moryx.Cli.Commands/Extensions/ConfigExtensions.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,24 @@ namespace Moryx.Cli.Commands.Extensions
55
{
66
public static class ConfigExtensions
77
{
8-
public static TemplateSettings AsTemplateSettings(this Config.Models.Configuration configuration, string dir, string solutionName, string profile = "default")
9-
=> new()
8+
public static TemplateSettings AsTemplateSettings(this Config.Models.Configuration configuration, string dir, string solutionName, string profile = null)
9+
{
10+
profile = string.IsNullOrEmpty(profile) ? configuration.DefaultProfile : profile;
11+
return new()
1012
{
1113
Branch = configuration.Profiles[profile].Branch,
1214
Repository = configuration.Profiles[profile].Repository,
1315
AppName = solutionName,
1416
TargetDirectory = dir,
1517
};
18+
}
1619

17-
public static TemplateSettings LoadSettings(string dir, string solutionName, string profile = "default")
18-
=> Config.Models.Configuration.Load(dir).AsTemplateSettings(dir, solutionName, profile);
20+
public static TemplateSettings LoadSettings(string dir, string solutionName, string profile = "")
21+
{
22+
var config = Config.Models.Configuration.Load(dir);
23+
profile = string.IsNullOrEmpty(profile) ? config.DefaultProfile : profile;
24+
return config.AsTemplateSettings(dir, solutionName, profile);
25+
}
1926

2027
public static Config.Models.Configuration ToConfiguration(this NewOptions options, string profile = "default")
2128
{

src/Moryx.Cli.Config/Models/Configuration.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
using Newtonsoft.Json;
22
using Newtonsoft.Json.Serialization;
3+
using System.ComponentModel;
34

45
namespace Moryx.Cli.Config.Models
56
{
67
public class Configuration
78
{
9+
private const string DefaultProfileName = "default";
10+
11+
public required string DefaultProfile { get; set; } = DefaultProfileName;
12+
813
public required Dictionary<string, Profile> Profiles { get; set; }
914

10-
public static Configuration Load(string directory) {
15+
public static Configuration Load(string directory)
16+
{
1117
try
1218
{
1319
using var file = File.OpenText(GetFilename(directory));
1420
var serializer = new JsonSerializer();
15-
return serializer.Deserialize(file, typeof(Configuration)) as Configuration ?? DefaultConfiguration();
16-
} catch (Exception)
21+
var config = serializer.Deserialize(file, typeof(Configuration)) as Configuration ?? DefaultConfiguration();
22+
config.DefaultProfile ??= DefaultProfileName;
23+
24+
return config;
25+
}
26+
catch (Exception)
1727
{
1828
return DefaultConfiguration();
1929
}
@@ -23,6 +33,7 @@ public static Configuration DefaultConfiguration()
2333
{
2434
return new Configuration
2535
{
36+
DefaultProfile = "default",
2637
Profiles = new Dictionary<string, Profile> { { "default",
2738
new Profile
2839
{
@@ -33,7 +44,7 @@ public static Configuration DefaultConfiguration()
3344
};
3445
}
3546

36-
public void Save(string directory)
47+
public void Save(string directory)
3748
{
3849
using var file = File.CreateText(GetFilename(directory));
3950
var serializer = new JsonSerializer

src/Moryx.Cli.Remotes/Add.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Moryx.Cli.Commands;
2+
using Moryx.Cli.Templates;
3+
4+
namespace Moryx.Cli.Remotes
5+
{
6+
public class Add
7+
{
8+
public static CommandResult Remote(AddOptions options)
9+
{
10+
CommandResult result = new();
11+
var dir = Directory.GetCurrentDirectory();
12+
Template.AssertSolution(
13+
dir,
14+
then => result = AddRemote(dir, options),
15+
error => result = CommandResult.WithError(error)
16+
);
17+
return result;
18+
}
19+
20+
private static CommandResult AddRemote(string dir, AddOptions options)
21+
{
22+
var remote = options.Name!;
23+
var localConfig = Config.Models.Configuration.Load(dir);
24+
25+
if (localConfig.Profiles.ContainsKey(remote))
26+
{
27+
return CommandResult.WithError($"A remote `{remote}` already exists.");
28+
}
29+
30+
localConfig.Profiles.Add(
31+
remote,
32+
new Config.Models.Profile
33+
{
34+
Repository = options.Repository!,
35+
Branch = options.Branch!
36+
});
37+
localConfig.Save(dir);
38+
39+
return CommandResult.IsOk($"Successfully added `{remote}`.");
40+
}
41+
}
42+
}

src/Moryx.Cli.Remotes/List.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using Moryx.Cli.Commands;
2+
using Moryx.Cli.Templates;
3+
4+
namespace Moryx.Cli.Remotes
5+
{
6+
public class List
7+
{
8+
public static CommandResult Get(Action<string> onStatus)
9+
{
10+
CommandResult result = new();
11+
var currentDir = Environment.CurrentDirectory;
12+
Template.AssertSolution(
13+
currentDir,
14+
then => result = ListRemotes(currentDir, onStatus),
15+
error => result = CommandResult.WithError(error)
16+
);
17+
18+
return result;
19+
}
20+
21+
private static CommandResult ListRemotes(string dir, Action<string> onStatus)
22+
{
23+
var config = Config.Models.Configuration.Load(dir);
24+
25+
var stringList =
26+
config?.Profiles?.Select(p => (p.Key == config.DefaultProfile ? "* " : " ")
27+
+ $"{p.Key}\t{p.Value.Repository}@{p.Value.Branch}").ToList() ?? [];
28+
29+
foreach (var profile in stringList)
30+
{
31+
onStatus(profile);
32+
}
33+
34+
return CommandResult.IsOk("");
35+
}
36+
}
37+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<ProjectReference Include="..\Moryx.Cli.Commands\Moryx.Cli.Commands.csproj" />
11+
</ItemGroup>
12+
13+
</Project>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+

2+
namespace Moryx.Cli.Remotes
3+
{
4+
public class AddOptions : RemoteOptions
5+
{
6+
public string? Repository { get; set; }
7+
8+
public string? Branch { get; set; }
9+
}
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+

2+
namespace Moryx.Cli.Remotes
3+
{
4+
public class PullOptions : RemoteOptions
5+
{
6+
}
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+

2+
namespace Moryx.Cli.Remotes
3+
{
4+
public class RemoteOptions
5+
{
6+
public string? Name { get; set; }
7+
}
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+

2+
namespace Moryx.Cli.Remotes
3+
{
4+
public class RemoveOptions : RemoteOptions
5+
{
6+
}
7+
}

0 commit comments

Comments
 (0)