This commit is contained in:
2022-11-01 15:01:20 +01:00
parent e379f8b83f
commit aa61ef3ce1
33 changed files with 890 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
namespace Alma.Command.Help;
public class HelpCommand : ICommand
{
private readonly Func<IEnumerable<ICommand>> _commandsProvider;
public string CommandString => "help";
public HelpCommand(Func<IEnumerable<ICommand>> commandsProvider)
{
_commandsProvider = commandsProvider;
}
public Task Run(List<string> parameters)
{
Console.WriteLine("Commands:" + Environment.NewLine);
foreach (var command in _commandsProvider().OrderBy(c => c.CommandString))
{
Console.WriteLine(command.CommandString);
}
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,10 @@
namespace Alma.Command.Info;
public class ModuleInfoCommand : ICommand
{
public string CommandString => "info";
public Task Run(List<string> parameters)
{
throw new NotImplementedException();
}
}

View File

@@ -0,0 +1,193 @@
using Alma.Configuration.Module;
using Alma.Configuration.Repository;
using Alma.Data;
using Alma.Services;
namespace Alma.Command.Link;
public class LinkCommand : ICommand
{
private readonly IRepositoryConfiguration _repositoryConfiguration;
private readonly IModuleConfigurationResolver _moduleConfigurationResolver;
private readonly IFolderService _folderService;
private readonly IMetadataHandler _metadataHandler;
public string CommandString => "link";
public LinkCommand(
IRepositoryConfiguration repositoryConfiguration,
IModuleConfigurationResolver moduleConfigurationResolver,
IFolderService folderService,
IMetadataHandler metadataHandler)
{
_repositoryConfiguration = repositoryConfiguration;
_moduleConfigurationResolver = moduleConfigurationResolver;
_folderService = folderService;
_metadataHandler = metadataHandler;
}
public async Task Run(List<string> parameters)
{
if (parameters.Count == 0)
{
Console.WriteLine("No module specified");
return;
}
string moduleName = parameters[0];
string sourceDirectory = Path.Combine(Environment.CurrentDirectory);
string targetDirectory = Path.Combine(Environment.CurrentDirectory, "..");
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))
{
Console.WriteLine("Source directory not exists: " + sourceDirectory);
return;
}
string moduleNameAsPath = moduleName.Replace('/', Path.DirectorySeparatorChar);
string moduleDirectory = Path.Combine(sourceDirectory, moduleNameAsPath);
if (!Directory.Exists(moduleDirectory))
{
Console.WriteLine("Module directory not exists: " + moduleDirectory);
return;
}
var moduleConfigFileStub = Path.Combine(moduleDirectory, Constants.ModuleConfigFileStub);
var (moduleConfiguration, moduleConfigurationFile) = await _moduleConfigurationResolver.ResolveModuleConfiguration(moduleConfigFileStub);
if (moduleConfiguration?.Target is string moduleTargetDir)
{
targetDirectory = ResolvePath(moduleTargetDir, targetDirectory);
}
if (!Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
}
var moduleConfigurationFileFullPath = moduleConfigurationFile is null ? null : Path.Combine(moduleDirectory, moduleConfigurationFile);
var moduleDir = new DirectoryInfo(moduleDirectory);
var currentTargetDirectory = new DirectoryInfo(targetDirectory);
var itemsToLink = (await TraverseTree(
moduleDir,
currentTargetDirectory,
moduleDir,
currentTargetDirectory,
moduleConfiguration)).ToList();
if (moduleConfigurationFile is not null) itemsToLink.RemoveAll(i => i.SourcePath == moduleConfigurationFileFullPath);
foreach (var itemToLink in itemsToLink)
{
Console.WriteLine($"Link: '{itemToLink.SourcePath}' '{itemToLink.TargetPath}'");
}
var successfulLinks = CreateLinks(itemsToLink);
await _metadataHandler.SaveLinkedItemsAsync(successfulLinks, moduleDir, currentTargetDirectory);
//await _metadataHandler.SaveLinkedItemsAsync(itemsToLink, moduleDir, currentTargetDirectory);
}
private List<ItemToLink> CreateLinks(List<ItemToLink> itemsToLink)
{
var successfulLinks = new List<ItemToLink>();
foreach (var itemToLink in itemsToLink)
{
if (File.Exists(itemToLink.TargetPath) || Directory.Exists(itemToLink.TargetPath))
{
Console.WriteLine("Item already exists: " + itemToLink.TargetPath);
continue;
}
var sourceFileExists = File.Exists(itemToLink.SourcePath);
var sourceDirectoryExists = Directory.Exists(itemToLink.SourcePath);
if (sourceFileExists)
{
File.CreateSymbolicLink(itemToLink.TargetPath, itemToLink.SourcePath);
}
else if (sourceDirectoryExists)
{
File.CreateSymbolicLink(itemToLink.TargetPath, itemToLink.SourcePath);
}
else
{
Console.WriteLine("Source not exists: " + itemToLink.SourcePath);
continue;
}
successfulLinks.Add(itemToLink);
}
return successfulLinks;
}
private async Task<IEnumerable<ItemToLink>> TraverseTree(
DirectoryInfo currentDirectory,
DirectoryInfo currentTargetDirectory,
DirectoryInfo moduleDirectory,
DirectoryInfo targetDirectory,
ModuleConfiguration? moduleConfiguration)
{
var filesToLink = new List<ItemToLink>();
foreach (var file in currentDirectory.GetFiles())
{
filesToLink.Add(new ItemToLink(Path.Combine(currentDirectory.FullName, file.Name), Path.Combine(currentTargetDirectory.FullName, file.Name)));
}
var subDirLinksToAdd = Enumerable.Empty<ItemToLink>();
foreach (var subDir in currentDirectory.GetDirectories())
{
var relativePath = GetRelativePath(subDir.FullName, moduleDirectory.FullName);
if (moduleConfiguration?.Links?.ContainsKey(relativePath) ?? false)
{
filesToLink.Add(new ItemToLink(subDir.FullName, ResolvePath(moduleConfiguration.Links[relativePath], targetDirectory.FullName)));
}
else
{
var subDirLinks = await TraverseTree(
subDir,
new DirectoryInfo(Path.Combine(currentTargetDirectory.FullName, subDir.Name)),
moduleDirectory,
targetDirectory,
moduleConfiguration
);
subDirLinksToAdd = subDirLinksToAdd.Concat(subDirLinks);
}
}
return filesToLink.Concat(subDirLinksToAdd);
}
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);
}

View File

@@ -0,0 +1,90 @@
using Alma.Configuration.Repository;
using Alma.Data;
using Alma.Services;
namespace Alma.Command.List;
public class ListCommand : ICommand
{
private readonly IRepositoryConfiguration _repositoryConfiguration;
private readonly IModuleConfigurationResolver _moduleConfigurationResolver;
public string CommandString => "ls";
public ListCommand(
IRepositoryConfiguration repositoryConfiguration,
IModuleConfigurationResolver moduleConfigurationResolver)
{
_repositoryConfiguration = repositoryConfiguration;
_moduleConfigurationResolver = moduleConfigurationResolver;
}
public async Task Run(List<string> parameters)
{
if (parameters.Count > 0)
{
await ListModulesByRepoName(parameters[0]);
}
else
{
await ListRepositories();
}
}
private async Task ListRepositories()
{
Console.WriteLine("Repositories:" + Environment.NewLine);
foreach (var repository in _repositoryConfiguration.Configuration.Repositories)
{
Console.WriteLine(repository.Name);
}
}
private async Task ListModulesByRepoName(string repositoryName)
{
var repo = _repositoryConfiguration.Configuration.Repositories.FirstOrDefault(r => r.Name == repositoryName);
if (repo is null)
{
Console.WriteLine($"No repository found with name '{repositoryName}'");
return;
}
if (repo.RepositoryPath is null)
{
Console.WriteLine($"No repository path is specified in repository settings '{repositoryName}'");
return;
}
await ListModules(repo.RepositoryPath, repositoryName);
}
private async Task ListModules(string repositoryPath, string repositoryName)
{
var repositoryDirectory = new DirectoryInfo(repositoryPath);
var moduleDirectories = await TraverseRepositoryFolder(repositoryDirectory);
Console.WriteLine($"Modules in repository '{repositoryName}':" + Environment.NewLine);
foreach (var modulePath in moduleDirectories)
{
Console.WriteLine(modulePath.FullName.Substring(repositoryDirectory.FullName.Length).Replace(Path.DirectorySeparatorChar, '/'));
}
}
private async Task<IEnumerable<DirectoryInfo>> TraverseRepositoryFolder(DirectoryInfo currentDirectory)
{
var moduleConfigFileStub = Path.Combine(currentDirectory.FullName, Constants.ModuleConfigFileStub);
var (moduleConfiguration, moduleConfigurationFile) = await _moduleConfigurationResolver.ResolveModuleConfiguration(moduleConfigFileStub);
var result = Enumerable.Empty<DirectoryInfo>();
if (moduleConfigurationFile is not null)
{
result = new List<DirectoryInfo> {currentDirectory};
}
foreach (var subDir in currentDirectory.GetDirectories())
{
result = result.Concat(await TraverseRepositoryFolder(subDir));
}
return result;
}
}

View File

@@ -0,0 +1,10 @@
namespace Alma.Command.Unlink;
public class UnlinkCommand : ICommand
{
public string CommandString => "unlink";
public Task Run(List<string> parameters)
{
throw new NotImplementedException();
}
}