diff --git a/src/Alma.Abstraction/Configuration/Module/ModuleConfiguration.cs b/src/Alma.Abstraction/Configuration/Module/ModuleConfiguration.cs index 22c9091..ace6c92 100644 --- a/src/Alma.Abstraction/Configuration/Module/ModuleConfiguration.cs +++ b/src/Alma.Abstraction/Configuration/Module/ModuleConfiguration.cs @@ -6,12 +6,14 @@ public class ModuleConfiguration public Dictionary? Links { get; set; } public string? Install { get; set; } - - public ModuleConfiguration(string? target, Dictionary? links, string? install) + public string? Configure { get; set; } + + public ModuleConfiguration(string? target, Dictionary? 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(mergedLinks), - merge.Install ?? Install + merge.Install ?? Install, + merge.Configure ?? Configure ); } public static ModuleConfiguration Empty() => - new(null, new Dictionary(), null); + new(null, new Dictionary(), null, null); } \ No newline at end of file diff --git a/src/Alma.Abstraction/Data/SpecialPathResolver.cs b/src/Alma.Abstraction/Data/SpecialPathResolver.cs new file mode 100644 index 0000000..8fe2653 --- /dev/null +++ b/src/Alma.Abstraction/Data/SpecialPathResolver.cs @@ -0,0 +1,3 @@ +namespace Alma.Data; + +public record SpecialPathResolver(string PathName, Func Resolver, bool? SkipCombiningCurrentDirectory = null); \ No newline at end of file diff --git a/src/Alma.Abstraction/Services/IPathHelperService.cs b/src/Alma.Abstraction/Services/IPathHelperService.cs new file mode 100644 index 0000000..b1f1d1d --- /dev/null +++ b/src/Alma.Abstraction/Services/IPathHelperService.cs @@ -0,0 +1,6 @@ +namespace Alma.Services; + +public interface IPathHelperService +{ + string ResolvePath(string path, string? currentDirectory = null); +} \ No newline at end of file diff --git a/src/Alma.App/Command/Configure/ConfigureCommand.cs b/src/Alma.App/Command/Configure/ConfigureCommand.cs new file mode 100644 index 0000000..3e80554 --- /dev/null +++ b/src/Alma.App/Command/Configure/ConfigureCommand.cs @@ -0,0 +1,75 @@ +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 _logger; + private readonly IModuleConfigurationResolver _moduleConfigurationResolver; + private readonly IShellService _shellService; + public override string CommandString => "configure"; + + public ConfigureCommand( + ILogger logger, + IRepositoryConfiguration repositoryConfiguration, + IModuleConfigurationResolver moduleConfigurationResolver, + IShellService shellService, + IPathHelperService pathHelperService) + : base(repositoryConfiguration, pathHelperService) + { + _logger = logger; + _moduleConfigurationResolver = moduleConfigurationResolver; + _shellService = shellService; + } + + public override async Task Run(List 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 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"); + } + } +} \ No newline at end of file diff --git a/src/Alma.App/Command/Info/InfoCommand.cs b/src/Alma.App/Command/Info/InfoCommand.cs index 41170a6..922f918 100644 --- a/src/Alma.App/Command/Info/InfoCommand.cs +++ b/src/Alma.App/Command/Info/InfoCommand.cs @@ -14,13 +14,15 @@ public class InfoCommand : ICommand private readonly ILogger _logger; private readonly IOsInformation _osInformation; private readonly IVersionService _versionService; + private readonly IPathHelperService _pathHelperService; public InfoCommand( IFolderService folderService, IRepositoryConfiguration repositoryConfiguration, ILogger logger, IOsInformation osInformation, - IVersionService versionService + IVersionService versionService, + IPathHelperService pathHelperService ) { _folderService = folderService; @@ -28,6 +30,7 @@ public class InfoCommand : ICommand _logger = logger; _osInformation = osInformation; _versionService = versionService; + _pathHelperService = pathHelperService; } public async Task Run(List parameters) @@ -59,7 +62,7 @@ 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})"); } diff --git a/src/Alma.App/Command/Install/InstallCommand.cs b/src/Alma.App/Command/Install/InstallCommand.cs index 370290e..6bbffdb 100644 --- a/src/Alma.App/Command/Install/InstallCommand.cs +++ b/src/Alma.App/Command/Install/InstallCommand.cs @@ -17,8 +17,9 @@ public class InstallCommand : RepositoryModuleCommandBase ILogger logger, IRepositoryConfiguration repositoryConfiguration, IModuleConfigurationResolver moduleConfigurationResolver, - IShellService shellService) - : base(repositoryConfiguration) + IShellService shellService, + IPathHelperService pathHelperService) + : base(repositoryConfiguration, pathHelperService) { _logger = logger; _moduleConfigurationResolver = moduleConfigurationResolver; diff --git a/src/Alma.App/Command/Link/LinkCommand.cs b/src/Alma.App/Command/Link/LinkCommand.cs index 40270c9..1d5431f 100644 --- a/src/Alma.App/Command/Link/LinkCommand.cs +++ b/src/Alma.App/Command/Link/LinkCommand.cs @@ -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 _logger; public override string CommandString => "link"; @@ -21,12 +22,14 @@ public class LinkCommand : RepositoryModuleCommandBase IRepositoryConfiguration repositoryConfiguration, IModuleConfigurationResolver moduleConfigurationResolver, IMetadataHandler metadataHandler, + IPathHelperService pathHelperService, ILogger logger) - : base(repositoryConfiguration) + : base(repositoryConfiguration, pathHelperService) { _repositoryConfiguration = repositoryConfiguration; _moduleConfigurationResolver = moduleConfigurationResolver; _metadataHandler = metadataHandler; + _pathHelperService = pathHelperService; _logger = logger; } @@ -64,7 +67,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 +133,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 +160,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 { diff --git a/src/Alma.App/Command/RepositoryModuleCommandBase.cs b/src/Alma.App/Command/RepositoryModuleCommandBase.cs index 3143a05..d7c4ac7 100644 --- a/src/Alma.App/Command/RepositoryModuleCommandBase.cs +++ b/src/Alma.App/Command/RepositoryModuleCommandBase.cs @@ -1,17 +1,22 @@ using Alma.Configuration.Repository; using Alma.Helper; +using Alma.Services; namespace Alma.Command; public abstract class RepositoryModuleCommandBase : ICommand { private readonly IRepositoryConfiguration _repositoryConfiguration; + private readonly IPathHelperService _pathHelperService; public abstract string CommandString { get; } public abstract Task Run(List parameters); - protected RepositoryModuleCommandBase(IRepositoryConfiguration repositoryConfiguration) + protected RepositoryModuleCommandBase( + IRepositoryConfiguration repositoryConfiguration, + IPathHelperService pathHelperService) { _repositoryConfiguration = repositoryConfiguration; + _pathHelperService = pathHelperService; } protected (string?, string?) GetRepositoryAndModuleName(List parameters) @@ -40,11 +45,11 @@ public abstract class RepositoryModuleCommandBase : ICommand { fallbackSourceDirectory = repoConfig.RepositoryPath is { } repoPath - ? PathHelper.ResolvePath(repoPath) + ? _pathHelperService.ResolvePath(repoPath) : fallbackSourceDirectory; fallbackTargetDirectory = repoConfig.LinkPath is { } linkPath - ? PathHelper.ResolvePath(linkPath) + ? _pathHelperService.ResolvePath(linkPath) : fallbackTargetDirectory; } diff --git a/src/Alma.App/Helper/PathHelper.cs b/src/Alma.App/Helper/PathHelper.cs deleted file mode 100644 index 9345152..0000000 --- a/src/Alma.App/Helper/PathHelper.cs +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/src/Alma.App/Services/PathHelperService.cs b/src/Alma.App/Services/PathHelperService.cs new file mode 100644 index 0000000..f5a5119 --- /dev/null +++ b/src/Alma.App/Services/PathHelperService.cs @@ -0,0 +1,39 @@ +using Alma.Data; + +namespace Alma.Services; + +public class PathHelperService : IPathHelperService +{ + private static List _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; + /*if (path.StartsWith("~")) + { + var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + path = path.Length > 1 ? Path.Combine(userProfile, path[2..]) : userProfile; + skipCombiningCurrentDirectory = true; + }*/ + + 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; + } + } + + //TODO: more special character + + return currentDirectory is null || skipCombiningCurrentDirectory + ? path + : Path.Combine(currentDirectory, path); + } +} \ No newline at end of file diff --git a/src/Alma/Program.cs b/src/Alma/Program.cs index 9c63a9d..2cf724a 100644 --- a/src/Alma/Program.cs +++ b/src/Alma/Program.cs @@ -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