Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 46c1a78e3f | |||
| fb381e56c5 |
75
.github/workflows/github-actions.yml
vendored
75
.github/workflows/github-actions.yml
vendored
@@ -1,75 +0,0 @@
|
||||
name: Alma build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.target.runner }}
|
||||
strategy:
|
||||
matrix:
|
||||
target:
|
||||
- runtime: win-x64
|
||||
runner: windows-latest
|
||||
name: windows
|
||||
outputname: Alma.exe
|
||||
version_script: .scripts/versioning.ps1
|
||||
- runtime: linux-x64
|
||||
runner: ubuntu-latest
|
||||
name: linux
|
||||
outputname: Alma
|
||||
version_script: .scripts/versioning.sh
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
- name: Patch version
|
||||
run: ${{ matrix.target.version_script }}
|
||||
continue-on-error: true
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore src/Alma
|
||||
- name: Build
|
||||
run: dotnet publish -c Release -p:PublishAot=true -r ${{ matrix.target.runtime }} -o app/ src/Alma
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: alma-${{ matrix.target.name }}
|
||||
path: app/${{ matrix.target.outputname }}
|
||||
|
||||
release:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download Windows artifacts
|
||||
with:
|
||||
name: alma-windows
|
||||
path: app/windows/
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download Linux artifacts
|
||||
with:
|
||||
name: alma-linux
|
||||
path: app/linux/
|
||||
|
||||
- name: Create release directory
|
||||
run: mkdir release
|
||||
|
||||
- name: Copy windows executable
|
||||
run: cp app/windows/Alma.exe release/alma.exe
|
||||
|
||||
- name: Copy linux executable
|
||||
run: cp app/linux/Alma release/alma-linux
|
||||
|
||||
- uses: "marvinpinto/action-automatic-releases@latest"
|
||||
name: Create release
|
||||
with:
|
||||
title: Test
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: latest
|
||||
prerelease: false
|
||||
draft: true
|
||||
files: |
|
||||
release/alma*
|
||||
@@ -1,15 +0,0 @@
|
||||
gci env:\
|
||||
|
||||
if((Get-Content env:\GITHUB_REF_TYPE) -ne "tag")
|
||||
{
|
||||
Return
|
||||
}
|
||||
|
||||
$version = (Get-Content env:\GITHUB_REF).Replace("refs/tags/v", "")
|
||||
$git_sha = (Get-Content env:\GITHUB_SHA).Substring(0, 8)
|
||||
|
||||
Write-Host $version
|
||||
Write-Host $git_sha
|
||||
|
||||
(Get-Content src\Alma\Alma.csproj).Replace("0.0.0", $version).Replace("development", $git_sha) | Set-Content src\Alma\Alma.csproj
|
||||
Write-Host (Get-Content src\Alma\Alma.csproj)
|
||||
@@ -1,16 +0,0 @@
|
||||
printenv
|
||||
|
||||
if [ ${GITHUB_REF_TYPE} != "tag" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
version="${GITHUB_REF:11}"
|
||||
git_hash="${GITHUB_SHA}"
|
||||
echo $git_hash
|
||||
git_hash=`expr substr $git_hash 1 8`
|
||||
|
||||
echo $version
|
||||
echo $git_hash
|
||||
|
||||
sed -i "s/0.0.0/$version/g;s/development/$git_hash/g" src/Alma/Alma.csproj
|
||||
cat src/Alma/Alma.csproj
|
||||
@@ -5,13 +5,10 @@ public class ModuleConfiguration
|
||||
public string? Target { get; set; }
|
||||
public Dictionary<string, string>? Links { get; set; }
|
||||
|
||||
public string? Install { get; set; }
|
||||
|
||||
public ModuleConfiguration(string? target, Dictionary<string, string>? links, string? install)
|
||||
public ModuleConfiguration(string? target, Dictionary<string, string>? links)
|
||||
{
|
||||
Target = target;
|
||||
Links = links;
|
||||
Install = install;
|
||||
}
|
||||
|
||||
public ModuleConfiguration Merge(ModuleConfiguration merge)
|
||||
@@ -20,11 +17,10 @@ public class ModuleConfiguration
|
||||
.Concat(merge.Links ?? new Dictionary<string, string>());
|
||||
return new ModuleConfiguration(
|
||||
merge.Target ?? Target,
|
||||
new Dictionary<string, string>(mergedLinks),
|
||||
merge.Install ?? Install
|
||||
new Dictionary<string, string>(mergedLinks)
|
||||
);
|
||||
}
|
||||
|
||||
public static ModuleConfiguration Empty() =>
|
||||
new(null, new Dictionary<string, string>(), null);
|
||||
new(null, new Dictionary<string, string>());
|
||||
}
|
||||
@@ -2,6 +2,6 @@ namespace Alma.Services;
|
||||
|
||||
public interface IOsInformation
|
||||
{
|
||||
Task<string> GetOsIdentifierAsync();
|
||||
Task<bool> IsOnPlatformAsync(string platform);
|
||||
string GetOsIdentifier();
|
||||
bool IsOnPlatform(string platform);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Alma.Services;
|
||||
|
||||
public interface IShellService
|
||||
{
|
||||
Task RunCommandAsync(string command);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Alma.Services;
|
||||
|
||||
public interface IVersionService
|
||||
{
|
||||
public string GetVersion();
|
||||
}
|
||||
@@ -5,10 +5,6 @@
|
||||
<ProjectReference Include="..\Alma.Logging\Alma.Logging.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -9,9 +9,9 @@ public class Application
|
||||
private readonly IList<ICommand> _commands;
|
||||
private readonly ILogger<Application> _logger;
|
||||
|
||||
public Application(IEnumerable<ICommand> commands, ILogger<Application> logger)
|
||||
public Application(IEnumerable<ICommand> commands, ILogger<Application> logger, ILogger<HelpCommand> helpCommandLogger)
|
||||
{
|
||||
_commands = commands.ToList();
|
||||
_commands = commands.Append(new HelpCommand(() => _commands!, helpCommandLogger)).ToList();
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ public class HelpCommand : ICommand
|
||||
public string CommandString => "help";
|
||||
|
||||
public HelpCommand(
|
||||
IServiceProvider serviceProvider,
|
||||
Func<IEnumerable<ICommand>> commandsProvider,
|
||||
ILogger<HelpCommand> logger
|
||||
)
|
||||
{
|
||||
_commandsProvider = () => (IEnumerable<ICommand>?)serviceProvider.GetService(typeof(IEnumerable<ICommand>)) ?? throw new ApplicationException();
|
||||
_commandsProvider = commandsProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +1,53 @@
|
||||
using Alma.Configuration.Repository;
|
||||
using Alma.Helper;
|
||||
using Alma.Logging;
|
||||
using Alma.Services;
|
||||
|
||||
namespace Alma.Command.Info;
|
||||
|
||||
public class InfoCommand : ICommand
|
||||
public class ModuleInfoCommand : ICommand
|
||||
{
|
||||
public string CommandString => "info";
|
||||
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly IRepositoryConfiguration _repositoryConfiguration;
|
||||
private readonly ILogger<InfoCommand> _logger;
|
||||
private readonly IOsInformation _osInformation;
|
||||
private readonly IVersionService _versionService;
|
||||
private readonly ILogger<ModuleInfoCommand> _logger;
|
||||
|
||||
public InfoCommand(
|
||||
public ModuleInfoCommand(
|
||||
IFolderService folderService,
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
ILogger<InfoCommand> logger,
|
||||
IOsInformation osInformation,
|
||||
IVersionService versionService
|
||||
ILogger<ModuleInfoCommand> logger
|
||||
)
|
||||
{
|
||||
_folderService = folderService;
|
||||
_repositoryConfiguration = repositoryConfiguration;
|
||||
_logger = logger;
|
||||
_osInformation = osInformation;
|
||||
_versionService = versionService;
|
||||
}
|
||||
|
||||
public async Task Run(List<string> parameters)
|
||||
public Task Run(List<string> parameters)
|
||||
{
|
||||
//Add info REPO
|
||||
//Add info REPO MODULE
|
||||
_logger.LogInformation("Alma " + _versionService.GetVersion());
|
||||
_logger.LogInformation("");
|
||||
|
||||
_logger.LogInformation("AppData folder: " + _folderService.AppData);
|
||||
|
||||
if (_folderService.ConfigRoot is { } configRoot)
|
||||
if (_folderService.ConfigRoot is string configRoot)
|
||||
{
|
||||
_logger.LogInformation("Configuration folder: " + configRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Configuration folder not exists.");
|
||||
_logger.LogInformation("Preferred configuration folder is: " + Path.Combine(_folderService.GetPreferredConfigurationFolder(), _folderService.ApplicationSubfolderName));
|
||||
_logger.LogInformation("Preffered configuration folder is: " + Path.Combine(_folderService.GetPreferredConfigurationFolder(), _folderService.ApplicationSubfolderName));
|
||||
}
|
||||
|
||||
_logger.LogInformation("");
|
||||
_logger.LogInformation($"Platform is '{await _osInformation.GetOsIdentifierAsync()}'");
|
||||
_logger.LogInformation("");
|
||||
|
||||
if (_repositoryConfiguration.Configuration.Repositories is {Count: > 0} repositories)
|
||||
if (_repositoryConfiguration.Configuration.Repositories is var repositores && repositores?.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Repositories:");
|
||||
foreach (var repository in repositories)
|
||||
foreach (var repository in repositores)
|
||||
{
|
||||
Console.Write(repository.Name);
|
||||
if (repository.RepositoryPath is not null && !Directory.Exists(PathHelper.ResolvePath(repository.RepositoryPath)))
|
||||
if (repository.RepositoryPath is not null && !Directory.Exists(repository.RepositoryPath))
|
||||
{
|
||||
Console.Write($" (containing folder not exists {repository.RepositoryPath})");
|
||||
}
|
||||
@@ -70,5 +58,7 @@ public class InfoCommand : ICommand
|
||||
{
|
||||
_logger.LogInformation("No repositories found");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using Alma.Configuration.Repository;
|
||||
using Alma.Data;
|
||||
using Alma.Logging;
|
||||
using Alma.Services;
|
||||
|
||||
namespace Alma.Command.Install;
|
||||
|
||||
public class InstallCommand : RepositoryModuleCommandBase
|
||||
{
|
||||
private readonly ILogger<InstallCommand> _logger;
|
||||
private readonly IModuleConfigurationResolver _moduleConfigurationResolver;
|
||||
private readonly IShellService _shellService;
|
||||
public override string CommandString => "install";
|
||||
|
||||
public InstallCommand(
|
||||
ILogger<InstallCommand> logger,
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
IModuleConfigurationResolver moduleConfigurationResolver,
|
||||
IShellService shellService)
|
||||
: base(repositoryConfiguration)
|
||||
{
|
||||
_logger = logger;
|
||||
_moduleConfigurationResolver = moduleConfigurationResolver;
|
||||
_shellService = shellService;
|
||||
}
|
||||
|
||||
public override async Task Run(List<string> parameters)
|
||||
{
|
||||
var (repoName, moduleName) = GetRepositoryAndModuleName(parameters);
|
||||
if (moduleName is null)
|
||||
{
|
||||
_logger.LogInformation("No module specified");
|
||||
return;
|
||||
}
|
||||
|
||||
string sourceDirectory = Path.Combine(Environment.CurrentDirectory);
|
||||
string targetDirectory = Path.Combine(Environment.CurrentDirectory, "..");
|
||||
|
||||
string moduleNameAsPath = moduleName.Replace('/', Path.DirectorySeparatorChar);
|
||||
(sourceDirectory, _) = GetModuleSourceAndTargetDirectory(repoName, sourceDirectory, targetDirectory);
|
||||
|
||||
string moduleDirectory = Path.Combine(sourceDirectory, moduleNameAsPath);
|
||||
|
||||
var moduleConfigFileStub = Path.Combine(moduleDirectory, Constants.ModuleConfigFileStub);
|
||||
var (moduleConfiguration, moduleConfigurationFile) = await _moduleConfigurationResolver.ResolveModuleConfiguration(moduleConfigFileStub);
|
||||
|
||||
if (moduleConfiguration is null)
|
||||
{
|
||||
_logger.LogInformation($"No module configuration found for module '{moduleName}'{(repoName is null ? "" : $" in repository '{repoName}'")}");
|
||||
return;
|
||||
}
|
||||
|
||||
var installLines = moduleConfiguration.Install?.Split(Environment.NewLine);
|
||||
|
||||
if (installLines is null)
|
||||
{
|
||||
_logger.LogInformation("No install command is found");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Install command: {string.Join("\n", installLines)}");
|
||||
|
||||
if (installLines.Length == 1)
|
||||
{
|
||||
_logger.LogInformation("Running install command '" + installLines[0] + "'");
|
||||
await _shellService.RunCommandAsync(installLines[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Multi line scripts are not currently supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,27 +2,25 @@ using System.Runtime.InteropServices;
|
||||
using Alma.Configuration.Module;
|
||||
using Alma.Configuration.Repository;
|
||||
using Alma.Data;
|
||||
using Alma.Helper;
|
||||
using Alma.Logging;
|
||||
using Alma.Services;
|
||||
|
||||
namespace Alma.Command.Link;
|
||||
|
||||
public class LinkCommand : RepositoryModuleCommandBase
|
||||
public class LinkCommand : ICommand
|
||||
{
|
||||
private readonly IRepositoryConfiguration _repositoryConfiguration;
|
||||
private readonly IModuleConfigurationResolver _moduleConfigurationResolver;
|
||||
private readonly IMetadataHandler _metadataHandler;
|
||||
private readonly ILogger<LinkCommand> _logger;
|
||||
|
||||
public override string CommandString => "link";
|
||||
public string CommandString => "link";
|
||||
|
||||
public LinkCommand(
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
IModuleConfigurationResolver moduleConfigurationResolver,
|
||||
IMetadataHandler metadataHandler,
|
||||
ILogger<LinkCommand> logger)
|
||||
: base(repositoryConfiguration)
|
||||
{
|
||||
_repositoryConfiguration = repositoryConfiguration;
|
||||
_moduleConfigurationResolver = moduleConfigurationResolver;
|
||||
@@ -30,19 +28,26 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task Run(List<string> parameters)
|
||||
public async Task Run(List<string> parameters)
|
||||
{
|
||||
var (repoName, moduleName) = GetRepositoryAndModuleName(parameters);
|
||||
if (moduleName is null)
|
||||
if (parameters.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("No module specified");
|
||||
return;
|
||||
}
|
||||
|
||||
string moduleName = parameters[0];
|
||||
|
||||
string sourceDirectory = Path.Combine(Environment.CurrentDirectory);
|
||||
string targetDirectory = Path.Combine(Environment.CurrentDirectory, "..");
|
||||
|
||||
(sourceDirectory, targetDirectory) = GetModuleSourceAndTargetDirectory(repoName, sourceDirectory, targetDirectory);
|
||||
var repoName = GetRepositoryName(parameters);
|
||||
if (repoName is not null
|
||||
&& _repositoryConfiguration.Configuration.Repositories.FirstOrDefault(r => r.Name == repoName) is { } repoConfig)
|
||||
{
|
||||
sourceDirectory = repoConfig.RepositoryPath ?? sourceDirectory;
|
||||
targetDirectory = repoConfig.LinkPath ?? targetDirectory;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
{
|
||||
@@ -64,7 +69,7 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
|
||||
if (moduleConfiguration?.Target is string moduleTargetDir)
|
||||
{
|
||||
targetDirectory = PathHelper.ResolvePath(moduleTargetDir, targetDirectory);
|
||||
targetDirectory = ResolvePath(moduleTargetDir, targetDirectory);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(targetDirectory))
|
||||
@@ -157,7 +162,7 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
var relativePath = GetRelativePath(subDir.FullName, moduleDirectory.FullName);
|
||||
if (moduleConfiguration?.Links?.ContainsKey(relativePath) ?? false)
|
||||
{
|
||||
filesToLink.Add(new ItemToLink(subDir.FullName, PathHelper.ResolvePath(moduleConfiguration.Links[relativePath], targetDirectory.FullName)));
|
||||
filesToLink.Add(new ItemToLink(subDir.FullName, ResolvePath(moduleConfiguration.Links[relativePath], targetDirectory.FullName)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -175,5 +180,24 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
return filesToLink.Concat(subDirLinksToAdd);
|
||||
}
|
||||
|
||||
private static string GetRelativePath(string full, string parent) => full[parent.Length..].TrimStart(Path.DirectorySeparatorChar);
|
||||
private static string? GetRepositoryName(List<string> parameters)
|
||||
{
|
||||
//TODO: handle parameters
|
||||
if (parameters.Count < 2) return null;
|
||||
return parameters[1];
|
||||
}
|
||||
|
||||
private static string ResolvePath(string path, string currentDirectory)
|
||||
{
|
||||
if (path.StartsWith("~"))
|
||||
{
|
||||
path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), path.Substring(2));
|
||||
}
|
||||
|
||||
//TODO: more special character
|
||||
|
||||
return Path.Combine(currentDirectory, path);
|
||||
}
|
||||
|
||||
private static string GetRelativePath(string full, string parent) => full.Substring(parent.Length).TrimStart(Path.DirectorySeparatorChar);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using Alma.Configuration.Repository;
|
||||
using Alma.Helper;
|
||||
|
||||
namespace Alma.Command;
|
||||
|
||||
public abstract class RepositoryModuleCommandBase : ICommand
|
||||
{
|
||||
private readonly IRepositoryConfiguration _repositoryConfiguration;
|
||||
public abstract string CommandString { get; }
|
||||
public abstract Task Run(List<string> parameters);
|
||||
|
||||
protected RepositoryModuleCommandBase(IRepositoryConfiguration repositoryConfiguration)
|
||||
{
|
||||
_repositoryConfiguration = repositoryConfiguration;
|
||||
}
|
||||
|
||||
protected (string?, string?) GetRepositoryAndModuleName(List<string> parameters)
|
||||
{
|
||||
//TODO: handle parameters
|
||||
string? repositoryName = null;
|
||||
string? moduleName = null;
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
moduleName = parameters[0];
|
||||
}
|
||||
else if (parameters.Count >= 1)
|
||||
{
|
||||
repositoryName = parameters[0];
|
||||
moduleName = parameters[1];
|
||||
}
|
||||
|
||||
return (repositoryName, moduleName);
|
||||
}
|
||||
|
||||
protected (string sourceDirectory, string targetDirectory) GetModuleSourceAndTargetDirectory(string? repoName, string fallbackSourceDirectory, string fallbackTargetDirectory)
|
||||
{
|
||||
if (repoName is not null
|
||||
&& _repositoryConfiguration.Configuration.Repositories.FirstOrDefault(r => r.Name == repoName) is { } repoConfig)
|
||||
{
|
||||
fallbackSourceDirectory =
|
||||
repoConfig.RepositoryPath is { } repoPath
|
||||
? PathHelper.ResolvePath(repoPath)
|
||||
: fallbackSourceDirectory;
|
||||
fallbackTargetDirectory =
|
||||
repoConfig.LinkPath is { } linkPath
|
||||
? PathHelper.ResolvePath(linkPath)
|
||||
: fallbackTargetDirectory;
|
||||
}
|
||||
|
||||
return (fallbackSourceDirectory, fallbackTargetDirectory);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
namespace Alma.Helper;
|
||||
|
||||
public static class PathHelper
|
||||
{
|
||||
public static string ResolvePath(string path, string? currentDirectory = null)
|
||||
{
|
||||
var skipCombiningCurrentDirectory = false;
|
||||
if (path.StartsWith("~"))
|
||||
{
|
||||
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
path = path.Length > 1 ? Path.Combine(userProfile, path[2..]) : userProfile;
|
||||
skipCombiningCurrentDirectory = true;
|
||||
}
|
||||
|
||||
//TODO: more special character
|
||||
|
||||
return currentDirectory is null || skipCombiningCurrentDirectory
|
||||
? path
|
||||
: Path.Combine(currentDirectory, path);
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,7 @@ public class ModuleConfigurationResolver : IModuleConfigurationResolver
|
||||
|
||||
if (moduleConfigRoot is null) return (null, null);
|
||||
|
||||
var validModuleConfigurations = await moduleConfigRoot
|
||||
.ToAsyncEnumerable()
|
||||
.WhereAwait(async m => await _osInformation.IsOnPlatformAsync(m.Key))
|
||||
.ToListAsync();
|
||||
var validModuleConfigurations = moduleConfigRoot.Where(m => _osInformation.IsOnPlatform(m.Key));
|
||||
|
||||
//TODO: priority order
|
||||
var orderedValidModuleConfigurations = new Dictionary<string, ModuleConfiguration>(validModuleConfigurations);
|
||||
|
||||
@@ -6,52 +6,19 @@ public class OsInformation : IOsInformation
|
||||
{
|
||||
private const string OsIdentifierDefault = "default";
|
||||
private const string OsIdentifierWin = "windows";
|
||||
private const string OsIdentifierMac = "macos";
|
||||
private const string OsIdentifierFreeBsd = "freebsd";
|
||||
private const string OsIdentifierLinux = "linux";
|
||||
|
||||
private const string LinuxOsRelease = "/etc/os-release";
|
||||
|
||||
public async Task<string> GetOsIdentifierAsync()
|
||||
public string GetOsIdentifier()
|
||||
{
|
||||
string? baseOsIdentifier = null;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) baseOsIdentifier = OsIdentifierWin;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) baseOsIdentifier = OsIdentifierMac;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD)) baseOsIdentifier = OsIdentifierFreeBsd;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
baseOsIdentifier = OsIdentifierLinux;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return OsIdentifierWin;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return OsIdentifierLinux;
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(LinuxOsRelease))
|
||||
{
|
||||
var lines = await File.ReadAllLinesAsync(LinuxOsRelease);
|
||||
var distroName = lines.FirstOrDefault(l => l.StartsWith("id=", StringComparison.InvariantCultureIgnoreCase));
|
||||
if (distroName is not null)
|
||||
{
|
||||
distroName = distroName.ToLower().Substring(distroName.IndexOf("=", StringComparison.Ordinal) + 1);
|
||||
|
||||
baseOsIdentifier += "-" + distroName;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (baseOsIdentifier is null)
|
||||
return "unknown";
|
||||
|
||||
var architecture = RuntimeInformation.ProcessArchitecture.ToString().ToLower();
|
||||
|
||||
return baseOsIdentifier + "-" + architecture;
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public async Task<bool> IsOnPlatformAsync(string platform)
|
||||
public bool IsOnPlatform(string platform)
|
||||
{
|
||||
return platform == OsIdentifierDefault
|
||||
|| (await GetOsIdentifierAsync()).StartsWith(platform, StringComparison.InvariantCultureIgnoreCase);
|
||||
if (platform == OsIdentifierDefault) return true;
|
||||
return platform == GetOsIdentifier();
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Alma.Logging;
|
||||
|
||||
namespace Alma.Services;
|
||||
|
||||
public class ShellService : IShellService
|
||||
{
|
||||
private readonly ILogger<ShellService> _logger;
|
||||
|
||||
public ShellService(ILogger<ShellService> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task RunCommandAsync(string command)
|
||||
{
|
||||
Process? process;
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
process = CreateLinuxShell(command);
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
process = CreateWindowsShell(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Platform not supported");
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
if (!process.Start()) return;
|
||||
|
||||
var reader = process.StandardOutput;
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
var content = await reader.ReadLineAsync();
|
||||
|
||||
if (content is not null)
|
||||
{
|
||||
_logger.LogInformation(content);
|
||||
}
|
||||
}
|
||||
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
|
||||
private Process CreateLinuxShell(string command)
|
||||
{
|
||||
var processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "sh",
|
||||
ArgumentList = {"-c", command},
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardInput = true,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
return new Process {StartInfo = processStartInfo};
|
||||
}
|
||||
|
||||
private Process CreateWindowsShell(string command)
|
||||
{
|
||||
var processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
//TODO: customizable shell
|
||||
FileName = "pwsh",
|
||||
ArgumentList = {"-c", command},
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardInput = true,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
return new Process {StartInfo = processStartInfo};
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,4 @@ public interface ILogger<T>
|
||||
void LogDebug(string logMessage);
|
||||
void LogTrace(string logMessage);
|
||||
void Log(string logMessage, LogLevel logLevel);
|
||||
void LogError(string logMessage);
|
||||
void LogCritical(string logMessage);
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
public enum LogLevel
|
||||
{
|
||||
Critical,
|
||||
Error,
|
||||
Information,
|
||||
Debug,
|
||||
Trace
|
||||
|
||||
@@ -22,14 +22,4 @@ public class Logger<T> : ILogger<T>
|
||||
Console.WriteLine(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void LogError(string logMessage)
|
||||
{
|
||||
Log(logMessage, LogLevel.Error);
|
||||
}
|
||||
|
||||
public void LogCritical(string logMessage)
|
||||
{
|
||||
Log(logMessage, LogLevel.Critical);
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,6 @@
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<VersionPrefix>0.0.0</VersionPrefix>
|
||||
<VersionSuffix>development</VersionSuffix>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Alma.Command;
|
||||
using Alma.Command.Help;
|
||||
using Alma.Command.Info;
|
||||
using Alma.Command.Install;
|
||||
using Alma.Command.Link;
|
||||
using Alma.Command.List;
|
||||
using Alma.Command.Unlink;
|
||||
@@ -14,6 +12,42 @@ namespace Alma;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
/*public static async Task Main(string[] args)
|
||||
{
|
||||
var services = BuildServices();
|
||||
|
||||
var repositoryConfiguration = services.GetRequiredService<IRepositoryConfiguration>();
|
||||
await repositoryConfiguration.LoadAsync();
|
||||
var application = services.GetRequiredService<Application>();
|
||||
|
||||
await application.Run(args);
|
||||
|
||||
static IServiceProvider BuildServices()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
serviceCollection.AddSingleton<IRepositoryConfiguration, RepositoryConfiguration>();
|
||||
serviceCollection.AddSingleton<IFolderService, FolderService>();
|
||||
serviceCollection.AddSingleton<ConfigurationFileReader>();
|
||||
serviceCollection.AddSingleton<IConfigurationFileReader, JsonConfigurationFileReader>();
|
||||
serviceCollection.AddSingleton<IOsInformation, OsInformation>();
|
||||
serviceCollection.AddSingleton<ICommand, LinkCommand>();
|
||||
serviceCollection.AddSingleton<IModuleConfigurationResolver, ModuleConfigurationResolver>();
|
||||
serviceCollection.AddSingleton<Application>();
|
||||
|
||||
typeof(IRepositoryConfiguration), typeof(RepositoryConfiguration)
|
||||
typeof(IFolderService), typeof(FolderService)
|
||||
typeof(ConfigurationFileReader)
|
||||
typeof(IConfigurationFileReader), typeof(JsonConfigurationFileReader)
|
||||
typeof(IOsInformation), typeof(OsInformation)
|
||||
typeof(ICommand), typeof(LinkCommand)
|
||||
typeof(IModuleConfigurationResolver), typeof(ModuleConfigurationResolver)
|
||||
typeof(Application)
|
||||
|
||||
return serviceCollection.BuildServiceProvider();
|
||||
}
|
||||
}*/
|
||||
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
InitLogging();
|
||||
@@ -27,12 +61,14 @@ public static class Program
|
||||
await application.Run(args);
|
||||
}
|
||||
|
||||
private static void InitLogging()
|
||||
private static ILoggerFactory InitLogging()
|
||||
{
|
||||
AlmaLoggerFactory = new LoggerFactory();
|
||||
var loggerFactory = new LoggerFactory();
|
||||
|
||||
return AlmaLoggerFactory = loggerFactory;
|
||||
}
|
||||
|
||||
public static ILoggerFactory AlmaLoggerFactory { get; private set; } = null!;
|
||||
public static ILoggerFactory AlmaLoggerFactory { get; private set; }
|
||||
}
|
||||
|
||||
[ServiceProvider]
|
||||
@@ -43,14 +79,12 @@ public static class Program
|
||||
[Singleton(typeof(IOsInformation), typeof(OsInformation))]
|
||||
[Singleton(typeof(ICommand), typeof(LinkCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(UnlinkCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(InfoCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(ModuleInfoCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(ListCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(InstallCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(HelpCommand))]
|
||||
//Dependency cycle
|
||||
//[Singleton(typeof(ICommand), typeof(HelpCommand))]
|
||||
[Singleton(typeof(IModuleConfigurationResolver), typeof(ModuleConfigurationResolver))]
|
||||
[Singleton(typeof(IMetadataHandler), typeof(MetadataHandler))]
|
||||
[Singleton(typeof(IShellService), typeof(ShellService))]
|
||||
[Singleton(typeof(IVersionService), typeof(VersionService))]
|
||||
[Singleton(typeof(Application))]
|
||||
[Transient(typeof(ILogger<>), Factory = nameof(CustomLoggerFactory))]
|
||||
internal partial class AlmaServiceProvider
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Reflection;
|
||||
using Alma.Services;
|
||||
|
||||
namespace Alma;
|
||||
|
||||
public class VersionService : IVersionService
|
||||
{
|
||||
public string GetVersion()
|
||||
{
|
||||
return
|
||||
typeof(Program).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion
|
||||
?? typeof(Program).Assembly.GetName().Version?.ToString()
|
||||
?? "unknown";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user