Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions KtsuTools.Image/ImageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace KtsuTools.Image;
using System.Globalization;
using System.IO;

using ktsu.Semantics.Paths;

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
Expand All @@ -31,17 +33,22 @@ public static class ImageService
/// <param name="padding">Padding in pixels added around the content. Must be less than size / 2.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>The number of successfully processed files.</returns>
public static async Task<int> ProcessAsync(string inputPath, string outputPath, string color = "#FFFFFF", int size = 128, int padding = 0, CancellationToken ct = default)
public static async Task<int> ProcessAsync(AbsoluteDirectoryPath inputPath, AbsoluteDirectoryPath outputPath, string color = "#FFFFFF", int size = 128, int padding = 0, CancellationToken ct = default)
{
Ensure.NotNull(inputPath);
Ensure.NotNull(outputPath);
Ensure.NotNull(color);

if (!ValidateArguments(inputPath, outputPath, size, padding))
string inputDir = inputPath.ToString();
string outputDir = outputPath.ToString();

if (!ValidateArguments(inputDir, outputDir, size, padding))
{
return 0;
}

Rgba32 targetColor = ParseHexColor(color);
string[] files = Directory.GetFiles(inputPath);
string[] files = Directory.GetFiles(inputDir);
int processedCount = 0;

await AnsiConsole.Progress()
Expand All @@ -58,7 +65,7 @@ await AnsiConsole.Progress()
foreach (string file in files)
{
ct.ThrowIfCancellationRequested();
bool succeeded = ProcessFileWithErrorHandling(file, outputPath, targetColor, size, padding);
bool succeeded = ProcessFileWithErrorHandling(file, outputDir, targetColor, size, padding);

if (succeeded)
{
Expand Down
1 change: 1 addition & 0 deletions KtsuTools.Image/KtsuTools.Image.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PackageReference Include="Spectre.Console" />
<PackageReference Include="SixLabors.ImageSharp" />
<PackageReference Include="ktsu.Extensions" />
<PackageReference Include="ktsu.Semantics.Paths" />
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions KtsuTools.Markdown/KtsuTools.Markdown.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<PackageReference Include="YamlDotNet" />
<PackageReference Include="ktsu.Frontmatter" />
<PackageReference Include="ktsu.Extensions" />
<PackageReference Include="ktsu.Semantics.Paths" />
</ItemGroup>

<ItemGroup>
Expand Down
11 changes: 7 additions & 4 deletions KtsuTools.Markdown/MarkdownService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace KtsuTools.Markdown;
using Spectre.Console;

using ktsu.Frontmatter;
using ktsu.Semantics.Paths;

/// <summary>
/// Service for cleaning and linting markdown files.
Expand All @@ -22,10 +23,11 @@ public class MarkdownService
/// <param name="ct">Cancellation token.</param>
/// <returns>The number of files that were modified.</returns>
#pragma warning disable CA1822, S2325 // Mark members as static - instance method required for DI injection
public async Task<int> CleanAsync(string directoryPath, bool applyLinting, bool standardizeLineEndings, CancellationToken ct)
public async Task<int> CleanAsync(AbsoluteDirectoryPath directoryPath, bool applyLinting, bool standardizeLineEndings, CancellationToken ct)
#pragma warning restore CA1822, S2325
{
string fullPath = Path.GetFullPath(directoryPath);
Ensure.NotNull(directoryPath);
string fullPath = directoryPath.ToString();

if (!Directory.Exists(fullPath))
{
Expand Down Expand Up @@ -78,10 +80,11 @@ await AnsiConsole.Progress()
/// <param name="ct">Cancellation token.</param>
/// <returns>The number of files that were modified.</returns>
#pragma warning disable CA1822, S2325 // Mark members as static - instance method required for DI injection
public async Task<int> LintAsync(string directoryPath, CancellationToken ct)
public async Task<int> LintAsync(AbsoluteDirectoryPath directoryPath, CancellationToken ct)
#pragma warning restore CA1822, S2325
{
string fullPath = Path.GetFullPath(directoryPath);
Ensure.NotNull(directoryPath);
string fullPath = directoryPath.ToString();

if (!Directory.Exists(fullPath))
{
Expand Down
1 change: 1 addition & 0 deletions KtsuTools.Packages/KtsuTools.Packages.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<ItemGroup>
<PackageReference Include="Spectre.Console" />
<PackageReference Include="ktsu.Semantics.Paths" />
</ItemGroup>

<ItemGroup>
Expand Down
25 changes: 19 additions & 6 deletions KtsuTools.Packages/PackagesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace KtsuTools.Packages;
using System.Net.Http;
using System.Text.Json;
using System.Xml.Linq;
using ktsu.Semantics.Paths;
using KtsuTools.Core.Services.Process;
using Spectre.Console;

Expand All @@ -21,14 +22,26 @@ public class PackagesService(IProcessService processService)
private static readonly HttpClient SharedHttpClient = new();

/// <summary>
/// Updates NuGet packages in projects at the specified path.
/// Updates NuGet packages in all .csproj files under the specified directory.
/// </summary>
public async Task<int> UpdateAsync(string path, bool whatIf = false, bool includePrerelease = false, string source = "nuget", CancellationToken ct = default)
public Task<int> UpdateAsync(AbsoluteDirectoryPath path, bool whatIf = false, bool includePrerelease = false, string source = "nuget", CancellationToken ct = default)
{
Ensure.NotNull(path);
return UpdateInternalAsync(path.ToString(), whatIf, includePrerelease, source, ct);
}

/// <summary>
/// Updates NuGet packages in a single .csproj file.
/// </summary>
public Task<int> UpdateAsync(AbsoluteFilePath path, bool whatIf = false, bool includePrerelease = false, string source = "nuget", CancellationToken ct = default)
{
_ = processService;
Ensure.NotNull(path);
return UpdateInternalAsync(path.ToString(), whatIf, includePrerelease, source, ct);
}

string fullPath = Path.GetFullPath(path);
private async Task<int> UpdateInternalAsync(string fullPath, bool whatIf, bool includePrerelease, string source, CancellationToken ct)
{
_ = processService;

if (!Directory.Exists(fullPath) && !File.Exists(fullPath))
{
Expand Down Expand Up @@ -77,12 +90,12 @@ await AnsiConsole.Progress()
/// <summary>
/// Migrates projects to Central Package Management.
/// </summary>
public async Task<int> MigrateToCpmAsync(string path, CancellationToken ct = default)
public async Task<int> MigrateToCpmAsync(AbsoluteDirectoryPath path, CancellationToken ct = default)
{
_ = processService;
Ensure.NotNull(path);

string fullPath = Path.GetFullPath(path);
string fullPath = path.ToString();

if (!Directory.Exists(fullPath))
{
Expand Down
1 change: 1 addition & 0 deletions KtsuTools.Repo/KtsuTools.Repo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<ItemGroup>
<PackageReference Include="Spectre.Console" />
<PackageReference Include="ktsu.Semantics.Paths" />
</ItemGroup>

<ItemGroup>
Expand Down
17 changes: 9 additions & 8 deletions KtsuTools.Repo/RepoService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace KtsuTools.Repo;

using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using ktsu.Semantics.Paths;
using KtsuTools.Core.Services.Git;
using KtsuTools.Core.Services.Process;
using Spectre.Console;
Expand Down Expand Up @@ -38,12 +39,12 @@ public class RepoService(IGitService gitService, IProcessService processService)
/// <summary>
/// Discovers git repositories in the given directory.
/// </summary>
public async Task<IReadOnlyList<string>> DiscoverRepositoriesAsync(string path, CancellationToken ct = default)
public async Task<IReadOnlyList<string>> DiscoverRepositoriesAsync(AbsoluteDirectoryPath path, CancellationToken ct = default)
{
_ = gitService;
Ensure.NotNull(path);

string fullPath = Path.GetFullPath(path);
string fullPath = path.ToString();

if (!Directory.Exists(fullPath))
{
Expand Down Expand Up @@ -85,12 +86,12 @@ await AnsiConsole.Status()
/// <summary>
/// Builds and tests all solutions found in repositories under the given path.
/// </summary>
public async Task<int> BuildAndTestAsync(string path, bool parallel = false, CancellationToken ct = default)
public async Task<int> BuildAndTestAsync(AbsoluteDirectoryPath path, bool parallel = false, CancellationToken ct = default)
{
_ = parallel;
Ensure.NotNull(path);

string fullPath = Path.GetFullPath(path);
string fullPath = path.ToString();
List<string> solutionFiles = DiscoverSolutionFiles(fullPath);

if (solutionFiles.Count == 0)
Expand Down Expand Up @@ -157,12 +158,12 @@ await AnsiConsole.Progress()
/// <summary>
/// Pulls all repositories under the given path.
/// </summary>
public async Task<int> PullAllAsync(string path, CancellationToken ct = default)
public async Task<int> PullAllAsync(AbsoluteDirectoryPath path, CancellationToken ct = default)
{
_ = gitService;
Ensure.NotNull(path);

string fullPath = Path.GetFullPath(path);
string fullPath = path.ToString();
ConcurrentBag<string> repos = [];
DiscoverGitReposRecursive(fullPath, repos);

Expand Down Expand Up @@ -223,11 +224,11 @@ await AnsiConsole.Progress()
/// <summary>
/// Updates NuGet packages in all projects under the given path.
/// </summary>
public async Task<int> UpdatePackagesAsync(string path, bool includePrerelease = false, CancellationToken ct = default)
public async Task<int> UpdatePackagesAsync(AbsoluteDirectoryPath path, bool includePrerelease = false, CancellationToken ct = default)
{
Ensure.NotNull(path);

string fullPath = Path.GetFullPath(path);
string fullPath = path.ToString();
List<string> solutionFiles = DiscoverSolutionFiles(fullPath);

if (solutionFiles.Count == 0)
Expand Down
1 change: 1 addition & 0 deletions KtsuTools.SvnMigrate/KtsuTools.SvnMigrate.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<ItemGroup>
<PackageReference Include="Spectre.Console" />
<PackageReference Include="ktsu.Semantics.Paths" />
</ItemGroup>

<ItemGroup>
Expand Down
10 changes: 6 additions & 4 deletions KtsuTools.SvnMigrate/SvnMigrateService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace KtsuTools.SvnMigrate;

using ktsu.Semantics.Paths;
using KtsuTools.Core.Services.Process;
using Spectre.Console;

Expand All @@ -17,15 +18,16 @@ public class SvnMigrateService(IProcessService processService)
/// <summary>
/// Migrates an SVN repository to Git.
/// </summary>
public async Task<int> MigrateAsync(Uri svnUrl, string targetPath, string? authorsFile = null, bool preserveEmptyDirs = true, CancellationToken ct = default)
public async Task<int> MigrateAsync(Uri svnUrl, AbsoluteDirectoryPath targetPath, AbsoluteFilePath? authorsFile = null, bool preserveEmptyDirs = true, CancellationToken ct = default)
{
Ensure.NotNull(svnUrl);
Ensure.NotNull(targetPath);

string gitRepoPath = Path.GetFullPath(targetPath);
string gitRepoPath = targetPath.ToString();
string? authorsFilePath = authorsFile?.ToString();

// Validate prerequisites
List<string> errors = await ValidateAsync(svnUrl, gitRepoPath, authorsFile, ct).ConfigureAwait(false);
List<string> errors = await ValidateAsync(svnUrl, gitRepoPath, authorsFilePath, ct).ConfigureAwait(false);
if (errors.Count > 0)
{
foreach (string error in errors)
Expand Down Expand Up @@ -53,7 +55,7 @@ await AnsiConsole.Progress()

// Phase 1: Clone SVN repository
task.Description = "[green]Cloning SVN repository with git-svn...[/]";
await CloneSvnRepositoryAsync(svnUrl.ToString(), gitRepoPath, authorsFile, preserveEmptyDirs, ct).ConfigureAwait(false);
await CloneSvnRepositoryAsync(svnUrl.ToString(), gitRepoPath, authorsFilePath, preserveEmptyDirs, ct).ConfigureAwait(false);
task.Value = 50;

// Phase 2: Cleanup references
Expand Down
21 changes: 12 additions & 9 deletions KtsuTools.Sync/SyncService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class SyncService(IProcessService processService)
/// <param name="filename">The filename pattern to scan for.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>Exit code (0 for success).</returns>
public Task<int> RunAsync(string path, string filename, CancellationToken ct = default) =>
public Task<int> RunAsync(AbsoluteDirectoryPath path, string filename, CancellationToken ct = default) =>
RunAsync(path, [filename], autoPush: false, ct);

/// <summary>
Expand All @@ -53,13 +53,16 @@ public Task<int> RunAsync(string path, string filename, CancellationToken ct = d
/// <param name="autoPush">When true, repos whose unpushed commits are all authored by KtsuTools are pushed without prompting.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>Exit code (0 for success).</returns>
public async Task<int> RunAsync(string path, IReadOnlyList<string> filenames, bool autoPush, CancellationToken ct = default)
public async Task<int> RunAsync(AbsoluteDirectoryPath path, IReadOnlyList<string> filenames, bool autoPush, CancellationToken ct = default)
{
Ensure.NotNull(path);
ct.ThrowIfCancellationRequested();

if (!Directory.Exists(path))
string pathString = path.ToString();

if (!Directory.Exists(pathString))
{
AnsiConsole.MarkupLine($"[red]Path does not exist: {path.EscapeMarkup()}[/]");
AnsiConsole.MarkupLine($"[red]Path does not exist: {pathString.EscapeMarkup()}[/]");
return 1;
}

Expand All @@ -75,14 +78,14 @@ public async Task<int> RunAsync(string path, IReadOnlyList<string> filenames, bo
}

AnsiConsole.MarkupLine($"[bold]Scanning for:[/] {string.Join(", ", patterns).EscapeMarkup()}");
AnsiConsole.MarkupLine($"[bold]In:[/] {path.EscapeMarkup()}");
AnsiConsole.MarkupLine($"[bold]In:[/] {pathString.EscapeMarkup()}");
AnsiConsole.WriteLine();

HashSet<string> seen = new(StringComparer.Ordinal);
Collection<string> fileEnumeration = [];
foreach (string pattern in patterns)
{
foreach (string file in Directory.EnumerateFiles(path, pattern, SearchOption.AllDirectories)
foreach (string file in Directory.EnumerateFiles(pathString, pattern, SearchOption.AllDirectories)
.Where(f => !IsRepoNested(AbsoluteFilePath.Create<AbsoluteFilePath>(f).AbsoluteDirectoryPath)))
{
if (seen.Add(file))
Expand All @@ -103,12 +106,12 @@ public async Task<int> RunAsync(string path, IReadOnlyList<string> filenames, bo
foreach (string uniqueFilename in uniqueFilenames)
{
ct.ThrowIfCancellationRequested();
await ProcessUniqueFilenameAsync(uniqueFilename, fileEnumeration, path, commitDirectories, ct).ConfigureAwait(false);
await ProcessUniqueFilenameAsync(uniqueFilename, fileEnumeration, pathString, commitDirectories, ct).ConfigureAwait(false);
}

await CommitChangedFilesAsync(commitDirectories, expandedFilesToSync, path).ConfigureAwait(false);
await CommitChangedFilesAsync(commitDirectories, expandedFilesToSync, pathString).ConfigureAwait(false);

await PushToRemoteAsync(commitDirectories, path, autoPush, ct).ConfigureAwait(false);
await PushToRemoteAsync(commitDirectories, pathString, autoPush, ct).ConfigureAwait(false);

return 0;
}
Expand Down
7 changes: 5 additions & 2 deletions KtsuTools.Test/RepoServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace KtsuTools.Test;

using System.IO;
using ktsu.Semantics.Paths;
using KtsuTools.Core.Services.Git;
using KtsuTools.Core.Services.Process;
using KtsuTools.Repo;
Expand All @@ -18,7 +19,8 @@ public async Task DiscoverRepositoriesAsyncMissingDirectoryReturnsEmpty()
{
RepoService service = new(new Mock<IGitService>().Object, new Mock<IProcessService>().Object);
string missing = Path.Combine(Path.GetTempPath(), $"ktsu_missing_{Guid.NewGuid():N}");
IReadOnlyList<string> result = await service.DiscoverRepositoriesAsync(missing).ConfigureAwait(false);
AbsoluteDirectoryPath missingPath = AbsoluteDirectoryPath.Create<AbsoluteDirectoryPath>(missing);
IReadOnlyList<string> result = await service.DiscoverRepositoriesAsync(missingPath).ConfigureAwait(false);
Assert.AreEqual(0, result.Count);
}

Expand All @@ -35,7 +37,8 @@ public async Task DiscoverRepositoriesAsyncFindsGitDirectories()
try
{
RepoService service = new(new Mock<IGitService>().Object, new Mock<IProcessService>().Object);
IReadOnlyList<string> result = await service.DiscoverRepositoriesAsync(root).ConfigureAwait(false);
AbsoluteDirectoryPath rootPath = AbsoluteDirectoryPath.Create<AbsoluteDirectoryPath>(root);
IReadOnlyList<string> result = await service.DiscoverRepositoriesAsync(rootPath).ConfigureAwait(false);
Assert.AreEqual(2, result.Count, "Should find exactly the two .git directories.");
CollectionAssert.AreEquivalent(
new[] { repoA, repoB },
Expand Down
8 changes: 6 additions & 2 deletions KtsuTools/Commands/ImageProcessCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace KtsuTools.Commands;

using System.ComponentModel;
using System.IO;
using ktsu.Semantics.Paths;
using KtsuTools.Core.UI;
using KtsuTools.Image;
using Spectre.Console;
Expand Down Expand Up @@ -44,9 +46,11 @@ public override async Task<int> ExecuteAsync(CommandContext context, Settings se
AnsiConsole.MarkupLine("[bold]Image Process[/]");

using CtrlCScope scope = new();
AbsoluteDirectoryPath inputPath = AbsoluteDirectoryPath.Create<AbsoluteDirectoryPath>(Path.GetFullPath(settings.InputPath));
AbsoluteDirectoryPath outputPath = AbsoluteDirectoryPath.Create<AbsoluteDirectoryPath>(Path.GetFullPath(settings.OutputPath));
int processed = await ImageService.ProcessAsync(
settings.InputPath,
settings.OutputPath,
inputPath,
outputPath,
settings.Color,
settings.Size,
settings.Padding,
Expand Down
Loading
Loading