Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f5f01dd100 | |||
| a47f9b0826 | |||
| acbae0d18f | |||
| 68b00169d1 | |||
| ca28c26366 |
1
.github/workflows/github-actions.yml
vendored
1
.github/workflows/github-actions.yml
vendored
@@ -66,7 +66,6 @@ jobs:
|
||||
- uses: "marvinpinto/action-automatic-releases@latest"
|
||||
name: Create release
|
||||
with:
|
||||
title: Test
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: latest
|
||||
prerelease: false
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
gci env:\
|
||||
|
||||
if((Get-Content env:\GITHUB_REF_TYPE) -ne "tag")
|
||||
{
|
||||
Return
|
||||
@@ -11,5 +9,4 @@ $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)
|
||||
(Get-Content src\Alma\Alma.csproj).Replace("0.0.0", $version).Replace("development", $git_sha) | Set-Content src\Alma\Alma.csproj
|
||||
@@ -1,5 +1,3 @@
|
||||
printenv
|
||||
|
||||
if [ ${GITHUB_REF_TYPE} != "tag" ]; then
|
||||
exit 1
|
||||
fi
|
||||
@@ -12,5 +10,4 @@ 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
|
||||
sed -i "s/0.0.0/$version/g;s/development/$git_hash/g" src/Alma/Alma.csproj
|
||||
12
README.md
12
README.md
@@ -0,0 +1,12 @@
|
||||
# Alma
|
||||
|
||||
Alma (aka Advanced Link Manager Application) is another dotfiles management tool.
|
||||
|
||||
## Installation
|
||||
|
||||
**Linux**
|
||||
|
||||
```
|
||||
sudo wget https://github.com/ADIX7/Alma/releases/download/latest/alma-linux -O /usr/local/bin/alma
|
||||
sudo chmod +x /usr/local/bin/alma
|
||||
```
|
||||
@@ -6,12 +6,14 @@ public class ModuleConfiguration
|
||||
public Dictionary<string, string>? Links { get; set; }
|
||||
|
||||
public string? Install { get; set; }
|
||||
public string? Configure { get; set; }
|
||||
|
||||
public ModuleConfiguration(string? target, Dictionary<string, string>? links, string? install)
|
||||
public ModuleConfiguration(string? target, Dictionary<string, string>? links, string? install, string? configure)
|
||||
{
|
||||
Target = target;
|
||||
Links = links;
|
||||
Install = install;
|
||||
Configure = configure;
|
||||
}
|
||||
|
||||
public ModuleConfiguration Merge(ModuleConfiguration merge)
|
||||
@@ -21,10 +23,11 @@ public class ModuleConfiguration
|
||||
return new ModuleConfiguration(
|
||||
merge.Target ?? Target,
|
||||
new Dictionary<string, string>(mergedLinks),
|
||||
merge.Install ?? Install
|
||||
merge.Install ?? Install,
|
||||
merge.Configure ?? Configure
|
||||
);
|
||||
}
|
||||
|
||||
public static ModuleConfiguration Empty() =>
|
||||
new(null, new Dictionary<string, string>(), null);
|
||||
new(null, new Dictionary<string, string>(), null, null);
|
||||
}
|
||||
8
src/Alma.Abstraction/Data/ColorCodes.cs
Normal file
8
src/Alma.Abstraction/Data/ColorCodes.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Alma.Data;
|
||||
|
||||
public static class ColorCodes
|
||||
{
|
||||
public const string Reset = "\u001b[0m";
|
||||
public const string RedForeground = "\u001b[38;5;1m";
|
||||
public const string GreenForeground = "\u001b[38;5;2m";
|
||||
}
|
||||
5
src/Alma.Abstraction/Data/ModuleConfigurationWithName.cs
Normal file
5
src/Alma.Abstraction/Data/ModuleConfigurationWithName.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using Alma.Configuration.Module;
|
||||
|
||||
namespace Alma.Data;
|
||||
|
||||
public record ModuleConfigurationWithName(string Name, ModuleConfiguration Configuration);
|
||||
3
src/Alma.Abstraction/Data/SpecialPathResolver.cs
Normal file
3
src/Alma.Abstraction/Data/SpecialPathResolver.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
namespace Alma.Data;
|
||||
|
||||
public record SpecialPathResolver(string PathName, Func<string> Resolver, bool? SkipCombiningCurrentDirectory = null);
|
||||
6
src/Alma.Abstraction/Services/IPathHelperService.cs
Normal file
6
src/Alma.Abstraction/Services/IPathHelperService.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Alma.Services;
|
||||
|
||||
public interface IPathHelperService
|
||||
{
|
||||
string ResolvePath(string path, string? currentDirectory = null);
|
||||
}
|
||||
63
src/Alma.App/Command/Configure/ConfigureCommand.cs
Normal file
63
src/Alma.App/Command/Configure/ConfigureCommand.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Alma.Command.Install;
|
||||
using Alma.Configuration.Repository;
|
||||
using Alma.Data;
|
||||
using Alma.Logging;
|
||||
using Alma.Services;
|
||||
|
||||
namespace Alma.Command.Configure;
|
||||
|
||||
public class ConfigureCommand : RepositoryModuleCommandBase
|
||||
{
|
||||
private readonly ILogger<InstallCommand> _logger;
|
||||
private readonly IShellService _shellService;
|
||||
public override string CommandString => "configure";
|
||||
|
||||
public ConfigureCommand(
|
||||
ILogger<InstallCommand> logger,
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
IModuleConfigurationResolver moduleConfigurationResolver,
|
||||
IShellService shellService,
|
||||
IPathHelperService pathHelperService)
|
||||
: base(repositoryConfiguration, pathHelperService, moduleConfigurationResolver)
|
||||
{
|
||||
_logger = logger;
|
||||
_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;
|
||||
}
|
||||
var (moduleConfiguration, _) = await GetModuleConfiguration(repoName, moduleName);
|
||||
|
||||
if (moduleConfiguration is null)
|
||||
{
|
||||
_logger.LogInformation($"No module configuration found for module '{moduleName}'{(repoName is null ? "" : $" in repository '{repoName}'")}");
|
||||
return;
|
||||
}
|
||||
|
||||
var configureLines = moduleConfiguration.Configure?.Split(Environment.NewLine);
|
||||
|
||||
if (configureLines is null)
|
||||
{
|
||||
_logger.LogInformation("No configure command is found");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Configure command: {string.Join("\n", configureLines)}");
|
||||
|
||||
if (configureLines.Length == 1)
|
||||
{
|
||||
_logger.LogInformation("Running configure command '" + configureLines[0] + "'");
|
||||
await _shellService.RunCommandAsync(configureLines[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Multi line scripts are not currently supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,73 @@
|
||||
using Alma.Configuration.Module;
|
||||
using Alma.Configuration.Repository;
|
||||
using Alma.Data;
|
||||
using Alma.Helper;
|
||||
using Alma.Logging;
|
||||
using Alma.Services;
|
||||
|
||||
namespace Alma.Command.Info;
|
||||
|
||||
public class InfoCommand : ICommand
|
||||
public class InfoCommand : RepositoryModuleCommandBase
|
||||
{
|
||||
public string CommandString => "info";
|
||||
public override string CommandString => "info";
|
||||
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly IRepositoryConfiguration _repositoryConfiguration;
|
||||
private readonly IModuleConfigurationResolver _moduleConfigurationResolver;
|
||||
private readonly ILogger<InfoCommand> _logger;
|
||||
private readonly IOsInformation _osInformation;
|
||||
private readonly IVersionService _versionService;
|
||||
private readonly IPathHelperService _pathHelperService;
|
||||
|
||||
private static readonly List<Func<ModuleConfiguration, string?>> _moduleInfoDetailResolvers = new()
|
||||
{
|
||||
(m) =>
|
||||
{
|
||||
var linkCount = m.Links?.Count ?? 0;
|
||||
return linkCount.ToString().PadLeft(3) + $" link{(linkCount > 1 ? "s" : "")}".PadRight(6);
|
||||
},
|
||||
(m) => m.Install is not null ? "[Install]" : null,
|
||||
(m) => m.Configure is not null ? "[Configure]" : null,
|
||||
};
|
||||
|
||||
public InfoCommand(
|
||||
IFolderService folderService,
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
IModuleConfigurationResolver moduleConfigurationResolver,
|
||||
ILogger<InfoCommand> logger,
|
||||
IOsInformation osInformation,
|
||||
IVersionService versionService
|
||||
)
|
||||
IVersionService versionService,
|
||||
IPathHelperService pathHelperService
|
||||
) : base(repositoryConfiguration, pathHelperService, moduleConfigurationResolver)
|
||||
{
|
||||
_folderService = folderService;
|
||||
_repositoryConfiguration = repositoryConfiguration;
|
||||
_moduleConfigurationResolver = moduleConfigurationResolver;
|
||||
_logger = logger;
|
||||
_osInformation = osInformation;
|
||||
_versionService = versionService;
|
||||
_pathHelperService = pathHelperService;
|
||||
}
|
||||
|
||||
public async Task Run(List<string> parameters)
|
||||
public override async Task Run(List<string> parameters)
|
||||
{
|
||||
var (repoName, moduleName) = GetRepositoryAndModuleName(parameters, true);
|
||||
if (repoName is not null && moduleName is null)
|
||||
{
|
||||
await ProcessRepoInfoAsync(repoName);
|
||||
}
|
||||
else if (repoName is not null && moduleName is not null)
|
||||
{
|
||||
await ProcessModuleInfoAsync(repoName, moduleName);
|
||||
}
|
||||
else
|
||||
{
|
||||
await ProcessGeneralInfoAsync();
|
||||
}
|
||||
}
|
||||
|
||||
async Task ProcessGeneralInfoAsync()
|
||||
{
|
||||
//Add info REPO
|
||||
//Add info REPO MODULE
|
||||
_logger.LogInformation("Alma " + _versionService.GetVersion());
|
||||
_logger.LogInformation("");
|
||||
|
||||
@@ -59,10 +93,11 @@ public class InfoCommand : ICommand
|
||||
foreach (var repository in repositories)
|
||||
{
|
||||
Console.Write(repository.Name);
|
||||
if (repository.RepositoryPath is not null && !Directory.Exists(PathHelper.ResolvePath(repository.RepositoryPath)))
|
||||
if (repository.RepositoryPath is not null && !Directory.Exists(_pathHelperService.ResolvePath(repository.RepositoryPath)))
|
||||
{
|
||||
Console.Write($" (containing folder not exists {repository.RepositoryPath})");
|
||||
}
|
||||
|
||||
_logger.LogInformation("");
|
||||
}
|
||||
}
|
||||
@@ -71,4 +106,111 @@ public class InfoCommand : ICommand
|
||||
_logger.LogInformation("No repositories found");
|
||||
}
|
||||
}
|
||||
|
||||
async Task ProcessRepoInfoAsync(string repoName)
|
||||
{
|
||||
var (repoSourceDirectory, _) = GetRepositorySourceAndTargetDirectory(repoName);
|
||||
|
||||
var repoRoot = new DirectoryInfo(repoSourceDirectory);
|
||||
var modules = (await TraverseRepoFolder(repoRoot, repoRoot)).OrderBy(e => e.Name).ToList();
|
||||
|
||||
var maxNameLength = modules.Max(m => m.Name.Length);
|
||||
|
||||
_logger.LogInformation($"Repository '{repoName}' contains {modules.Count} modules:");
|
||||
_logger.LogInformation("");
|
||||
|
||||
foreach (var module in modules)
|
||||
{
|
||||
var moduleDetails = _moduleInfoDetailResolvers
|
||||
.Select(m => m(module.Configuration))
|
||||
.Where(m => m is not null)
|
||||
.ToList();
|
||||
_logger.LogInformation($"{module.Name.PadRight(maxNameLength + 3)} {string.Join(" ", moduleDetails)}");
|
||||
}
|
||||
}
|
||||
|
||||
async Task<IEnumerable<ModuleConfigurationWithName>> TraverseRepoFolder(DirectoryInfo repoRoot, DirectoryInfo currentDirectory)
|
||||
{
|
||||
var modulesFound = Enumerable.Empty<ModuleConfigurationWithName>();
|
||||
|
||||
var moduleConfigFileStub = Path.Combine(currentDirectory.FullName, Constants.ModuleConfigFileStub);
|
||||
var (moduleConfig, _) = await _moduleConfigurationResolver.ResolveModuleConfiguration(moduleConfigFileStub);
|
||||
|
||||
if (moduleConfig is not null)
|
||||
{
|
||||
var moduleName = currentDirectory.FullName[(repoRoot.FullName.Length + 1)..].Replace(Path.DirectorySeparatorChar, '/');
|
||||
modulesFound = modulesFound.Append(new(moduleName, moduleConfig));
|
||||
}
|
||||
|
||||
foreach (var subDir in currentDirectory.GetDirectories())
|
||||
{
|
||||
modulesFound = modulesFound.Concat(await TraverseRepoFolder(repoRoot, subDir));
|
||||
}
|
||||
|
||||
return modulesFound;
|
||||
}
|
||||
|
||||
async Task ProcessModuleInfoAsync(string repoName, string moduleName)
|
||||
{
|
||||
var (moduleConfiguration, moduleConfigFileName) = await GetModuleConfiguration(repoName, moduleName);
|
||||
|
||||
if (moduleConfiguration is null)
|
||||
{
|
||||
_logger.LogInformation($"No configuration is found for module '{moduleName}' in repository '{repoName}':");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation($"Information about module '{moduleName}' in repository '{repoName}':");
|
||||
_logger.LogInformation("");
|
||||
|
||||
var moduleTargetPath = moduleConfiguration.Target is not null
|
||||
? _pathHelperService.ResolvePath(moduleConfiguration.Target)
|
||||
: null;
|
||||
|
||||
if (moduleTargetPath is not null)
|
||||
{
|
||||
_logger.LogInformation($"Target directory is: {moduleTargetPath}");
|
||||
_logger.LogInformation("");
|
||||
}
|
||||
|
||||
if (moduleConfiguration.Install is not null)
|
||||
{
|
||||
_logger.LogInformation("Can be installed.");
|
||||
}
|
||||
|
||||
if (moduleConfiguration.Configure is not null)
|
||||
{
|
||||
_logger.LogInformation("Can be configured.");
|
||||
}
|
||||
|
||||
if (moduleConfiguration.Links is { } links && links.Count != 0)
|
||||
{
|
||||
var linkCount = links.Count;
|
||||
_logger.LogInformation("");
|
||||
_logger.LogInformation($"Has {linkCount} link{(linkCount > 1 ? "s" : "")}:");
|
||||
_logger.LogInformation("");
|
||||
|
||||
foreach (var link in links)
|
||||
{
|
||||
var sourcePath = Path.Combine(new FileInfo(moduleConfigFileName!).Directory!.FullName, link.Key);
|
||||
var sourceExists = File.Exists(sourcePath) || Directory.Exists(sourcePath);
|
||||
var sourceColor = sourceExists ? ColorCodes.GreenForeground : ColorCodes.RedForeground;
|
||||
|
||||
var targetColor = ColorCodes.RedForeground;
|
||||
if (moduleTargetPath is not null)
|
||||
{
|
||||
var targetPath = Path.Combine(moduleTargetPath, link.Key);
|
||||
var targetExists = File.Exists(targetPath) || Directory.Exists(targetPath);
|
||||
|
||||
targetColor = targetExists ? ColorCodes.GreenForeground : ColorCodes.RedForeground;
|
||||
}
|
||||
|
||||
_logger.LogInformation($"{sourceColor}{link.Key}{ColorCodes.Reset} -> {targetColor}{link.Value}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Has no links.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ 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";
|
||||
|
||||
@@ -17,11 +16,11 @@ public class InstallCommand : RepositoryModuleCommandBase
|
||||
ILogger<InstallCommand> logger,
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
IModuleConfigurationResolver moduleConfigurationResolver,
|
||||
IShellService shellService)
|
||||
: base(repositoryConfiguration)
|
||||
IShellService shellService,
|
||||
IPathHelperService pathHelperService)
|
||||
: base(repositoryConfiguration, pathHelperService, moduleConfigurationResolver)
|
||||
{
|
||||
_logger = logger;
|
||||
_moduleConfigurationResolver = moduleConfigurationResolver;
|
||||
_shellService = shellService;
|
||||
}
|
||||
|
||||
@@ -33,17 +32,7 @@ public class InstallCommand : RepositoryModuleCommandBase
|
||||
_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);
|
||||
var (moduleConfiguration, _) = await GetModuleConfiguration(repoName, moduleName);
|
||||
|
||||
if (moduleConfiguration is null)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
private readonly IRepositoryConfiguration _repositoryConfiguration;
|
||||
private readonly IModuleConfigurationResolver _moduleConfigurationResolver;
|
||||
private readonly IMetadataHandler _metadataHandler;
|
||||
private readonly IPathHelperService _pathHelperService;
|
||||
private readonly ILogger<LinkCommand> _logger;
|
||||
|
||||
public override string CommandString => "link";
|
||||
@@ -21,12 +22,14 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
IModuleConfigurationResolver moduleConfigurationResolver,
|
||||
IMetadataHandler metadataHandler,
|
||||
IPathHelperService pathHelperService,
|
||||
ILogger<LinkCommand> logger)
|
||||
: base(repositoryConfiguration)
|
||||
: base(repositoryConfiguration, pathHelperService, moduleConfigurationResolver)
|
||||
{
|
||||
_repositoryConfiguration = repositoryConfiguration;
|
||||
_moduleConfigurationResolver = moduleConfigurationResolver;
|
||||
_metadataHandler = metadataHandler;
|
||||
_pathHelperService = pathHelperService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -39,10 +42,7 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
return;
|
||||
}
|
||||
|
||||
string sourceDirectory = Path.Combine(Environment.CurrentDirectory);
|
||||
string targetDirectory = Path.Combine(Environment.CurrentDirectory, "..");
|
||||
|
||||
(sourceDirectory, targetDirectory) = GetModuleSourceAndTargetDirectory(repoName, sourceDirectory, targetDirectory);
|
||||
var (sourceDirectory, targetDirectory) = GetRepositorySourceAndTargetDirectory(repoName);
|
||||
|
||||
if (!Directory.Exists(sourceDirectory))
|
||||
{
|
||||
@@ -64,7 +64,7 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
|
||||
if (moduleConfiguration?.Target is string moduleTargetDir)
|
||||
{
|
||||
targetDirectory = PathHelper.ResolvePath(moduleTargetDir, targetDirectory);
|
||||
targetDirectory = _pathHelperService.ResolvePath(moduleTargetDir, targetDirectory);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(targetDirectory))
|
||||
@@ -130,7 +130,7 @@ public class LinkCommand : RepositoryModuleCommandBase
|
||||
_logger.LogInformation("An error occured while creating links: " + e.Message);
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
_logger.LogInformation("On Windows symlinks can be greated only with Administrator privileges.");
|
||||
_logger.LogInformation("On Windows symlinks can be created only with Administrator privileges.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,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, _pathHelperService.ResolvePath(moduleConfiguration.Links[relativePath], targetDirectory.FullName)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,20 +1,39 @@
|
||||
using Alma.Configuration.Repository;
|
||||
using Alma.Helper;
|
||||
using Alma.Data;
|
||||
using Alma.Services;
|
||||
|
||||
namespace Alma.Command;
|
||||
|
||||
public abstract class RepositoryModuleCommandBase : ICommand
|
||||
{
|
||||
private readonly IRepositoryConfiguration _repositoryConfiguration;
|
||||
private readonly IModuleConfigurationResolver _moduleConfigurationResolver;
|
||||
private readonly IPathHelperService _pathHelperService;
|
||||
public abstract string CommandString { get; }
|
||||
public abstract Task Run(List<string> parameters);
|
||||
|
||||
protected RepositoryModuleCommandBase(IRepositoryConfiguration repositoryConfiguration)
|
||||
protected RepositoryModuleCommandBase(
|
||||
IRepositoryConfiguration repositoryConfiguration,
|
||||
IPathHelperService pathHelperService,
|
||||
IModuleConfigurationResolver moduleConfigurationResolver)
|
||||
{
|
||||
_repositoryConfiguration = repositoryConfiguration;
|
||||
_pathHelperService = pathHelperService;
|
||||
_moduleConfigurationResolver = moduleConfigurationResolver;
|
||||
}
|
||||
|
||||
protected (string?, string?) GetRepositoryAndModuleName(List<string> parameters)
|
||||
protected async Task<(Configuration.Module.ModuleConfiguration? mergedModuleConfig, string? moduleConfigFileName)> GetModuleConfiguration(string? repoName, string moduleName)
|
||||
{
|
||||
var (repoSourceDirectory, _) = GetRepositorySourceAndTargetDirectory(repoName);
|
||||
|
||||
var moduleNameAsPath = moduleName.Replace('/', Path.DirectorySeparatorChar);
|
||||
var moduleDirectory = Path.Combine(repoSourceDirectory, moduleNameAsPath);
|
||||
|
||||
var moduleConfigFileStub = Path.Combine(moduleDirectory, Constants.ModuleConfigFileStub);
|
||||
return await _moduleConfigurationResolver.ResolveModuleConfiguration(moduleConfigFileStub);
|
||||
}
|
||||
|
||||
protected (string? repoName, string? moduleName) GetRepositoryAndModuleName(List<string> parameters, bool singleParamIsRepo = false)
|
||||
{
|
||||
//TODO: handle parameters
|
||||
string? repositoryName = null;
|
||||
@@ -22,7 +41,14 @@ public abstract class RepositoryModuleCommandBase : ICommand
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
moduleName = parameters[0];
|
||||
if (singleParamIsRepo)
|
||||
{
|
||||
repositoryName = parameters[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
moduleName = parameters[0];
|
||||
}
|
||||
}
|
||||
else if (parameters.Count >= 1)
|
||||
{
|
||||
@@ -33,18 +59,24 @@ public abstract class RepositoryModuleCommandBase : ICommand
|
||||
return (repositoryName, moduleName);
|
||||
}
|
||||
|
||||
protected (string sourceDirectory, string targetDirectory) GetModuleSourceAndTargetDirectory(string? repoName, string fallbackSourceDirectory, string fallbackTargetDirectory)
|
||||
protected (string repoSourceDirectory, string repoTargetDirectory) GetRepositorySourceAndTargetDirectory(string? repoName)
|
||||
{
|
||||
string repoSourceDirectory = Path.Combine(Environment.CurrentDirectory);
|
||||
string repoTargetDirectory = Path.Combine(Environment.CurrentDirectory, "..");
|
||||
return GetRepositorySourceAndTargetDirectory(repoName, repoSourceDirectory, repoTargetDirectory);
|
||||
}
|
||||
protected (string repoSourceDirectory, string repoTargetDirectory) GetRepositorySourceAndTargetDirectory(string? repoName, string fallbackSourceDirectory, string fallbackTargetDirectory)
|
||||
{
|
||||
if (repoName is not null
|
||||
&& _repositoryConfiguration.Configuration.Repositories.FirstOrDefault(r => r.Name == repoName) is { } repoConfig)
|
||||
&& _repositoryConfiguration.Configuration.Repositories.Find(r => r.Name == repoName) is { } repoConfig)
|
||||
{
|
||||
fallbackSourceDirectory =
|
||||
repoConfig.RepositoryPath is { } repoPath
|
||||
? PathHelper.ResolvePath(repoPath)
|
||||
? _pathHelperService.ResolvePath(repoPath)
|
||||
: fallbackSourceDirectory;
|
||||
fallbackTargetDirectory =
|
||||
repoConfig.LinkPath is { } linkPath
|
||||
? PathHelper.ResolvePath(linkPath)
|
||||
? _pathHelperService.ResolvePath(linkPath)
|
||||
: 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);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,11 @@ public class ModuleConfigurationResolver : IModuleConfigurationResolver
|
||||
//TODO: priority order
|
||||
var orderedValidModuleConfigurations = new Dictionary<string, ModuleConfiguration>(validModuleConfigurations);
|
||||
|
||||
if (orderedValidModuleConfigurations.Count == 0)
|
||||
{
|
||||
return (ModuleConfiguration.Empty(), moduleConfigFileName);
|
||||
}
|
||||
|
||||
var mergedModuleConfig = orderedValidModuleConfigurations
|
||||
.Select(m => m.Value)
|
||||
.Aggregate((a, b) => a.Merge(b));
|
||||
|
||||
33
src/Alma.App/Services/PathHelperService.cs
Normal file
33
src/Alma.App/Services/PathHelperService.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Alma.Data;
|
||||
|
||||
namespace Alma.Services;
|
||||
|
||||
public class PathHelperService : IPathHelperService
|
||||
{
|
||||
private static readonly List<SpecialPathResolver> _specialPathResolvers = new()
|
||||
{
|
||||
new("~", () => Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), true),
|
||||
new("%DOCUMENTS%", () => Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)),
|
||||
};
|
||||
|
||||
public string ResolvePath(string path, string? currentDirectory = null)
|
||||
{
|
||||
var skipCombiningCurrentDirectory = false;
|
||||
|
||||
foreach (var specialPathResolver in _specialPathResolvers)
|
||||
{
|
||||
if (path.Contains(specialPathResolver.PathName))
|
||||
{
|
||||
var parts = path.Split(specialPathResolver.PathName);
|
||||
path = string.Join(specialPathResolver.Resolver(), parts);
|
||||
skipCombiningCurrentDirectory = (specialPathResolver.SkipCombiningCurrentDirectory ?? false) || skipCombiningCurrentDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
path = path.Replace('/', Path.DirectorySeparatorChar);
|
||||
|
||||
return currentDirectory is null || skipCombiningCurrentDirectory
|
||||
? path
|
||||
: Path.Combine(currentDirectory, path);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Alma.Command;
|
||||
using Alma.Command.Configure;
|
||||
using Alma.Command.Help;
|
||||
using Alma.Command.Info;
|
||||
using Alma.Command.Install;
|
||||
@@ -47,10 +48,12 @@ public static class Program
|
||||
[Singleton(typeof(ICommand), typeof(ListCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(InstallCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(HelpCommand))]
|
||||
[Singleton(typeof(ICommand), typeof(ConfigureCommand))]
|
||||
[Singleton(typeof(IModuleConfigurationResolver), typeof(ModuleConfigurationResolver))]
|
||||
[Singleton(typeof(IMetadataHandler), typeof(MetadataHandler))]
|
||||
[Singleton(typeof(IShellService), typeof(ShellService))]
|
||||
[Singleton(typeof(IVersionService), typeof(VersionService))]
|
||||
[Singleton(typeof(IPathHelperService), typeof(PathHelperService))]
|
||||
[Singleton(typeof(Application))]
|
||||
[Transient(typeof(ILogger<>), Factory = nameof(CustomLoggerFactory))]
|
||||
internal partial class AlmaServiceProvider
|
||||
|
||||
Reference in New Issue
Block a user