Skip to content

Commit 8665d21

Browse files
authored
Merge pull request #16 from MORYX-Industry/feature/remotes
Add `remotes` feature which allows to manage 'source repositories' in a Git like manner.
2 parents 25d2cc2 + 91cde3a commit 8665d21

File tree

28 files changed

+572
-19
lines changed

28 files changed

+572
-19
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

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,29 @@ This is rather a workaround.
7272
### Examples
7373

7474
moryx exec create-dbs
75+
76+
77+
## Remotes
78+
79+
The CLI uses Git repositories as templates in order to create new application
80+
projects or add any kind of features to it.
81+
82+
By default, this repository is `https://github.com/PHOENIXCONTACT/MORYX-Template/tree/machine`
83+
if nothing else is provided to the `moryx new` command.
84+
85+
To change or switch later, from where to retrieve templates, `remotes` were
86+
introduced to manage template sources within a project.
87+
88+
### Usage
89+
90+
moryx remotes add <NAME> <URL> <BRANCH> Adds a Git remote to the local config
91+
moryx remotes remove <NAME> Removes Git remotes
92+
moryx remotes use <NAME> Uses the given remote by default
93+
94+
### Examples
95+
96+
moryx remotes
97+
moryx remotes add custom https://example.com/repo.git main
98+
moryx remotes remove custom
99+
moryx remotes use custom
100+

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 = "")
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+
}

0 commit comments

Comments
 (0)