Compare commits

..

No commits in common. "c65d6ed4147adb910b11d4fbe5e616efb452c71c" and "d2ca59e174ca9cd3392c46d0249a3023089a1188" have entirely different histories.

5 changed files with 27 additions and 166 deletions

View File

@ -1,66 +0,0 @@
name: Tagged Pre-Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+-*"
jobs:
release:
name: "Tagged Pre-Release"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Get version from tag
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}
- name: Build and Publish
run: |
dotnet publish -c Release -p PublishSingleFile=true -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }} -o ./publish/win-x64 -r win-x64
dotnet publish -c Release -p PublishSingleFile=true -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }} -o ./publish/win-x86 -r win-x86
dotnet publish -c Release -p PublishSingleFile=true -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }} -o ./publish/linux-x64 -r linux-x64
dotnet publish -c Release -p PublishSingleFile=true -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }} -o ./publish/osx-x64 -r osx-x64
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: publish
path: publish/
- name: Create Release
id: create_release
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
- name: Upload Release Assets
id: upload-release-assets
uses: actions/upload-release-asset@v1
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: |
./publish/win-x64/fdup.exe
./publish/win-x86/fdup.exe
./publish/linux-x64/fdup
./publish/osx-x64/fdup
asset_name: |
fdup-${{ steps.get_version.outputs.VERSION }}-win-x64.exe
fdup-${{ steps.get_version.outputs.VERSION }}-win-x86.exe
fdup-${{ steps.get_version.outputs.VERSION }}-linux_x64
fdup-${{ steps.get_version.outputs.VERSION }}-macos_x64
asset_content_type: application/octet-stream
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,66 +0,0 @@
name: Tagged Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
jobs:
release:
name: "Tagged Release"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Get version from tag
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}
- name: Build and Publish
run: |
dotnet publish -c Release -p PublishSingleFile=true -o ./publish/win-x64 -r win-x64
dotnet publish -c Release -p PublishSingleFile=true -o ./publish/win-x86 -r win-x86
dotnet publish -c Release -p PublishSingleFile=true -o ./publish/linux-x64 -r linux-x64
dotnet publish -c Release -p PublishSingleFile=true -o ./publish/osx-x64 -r osx-x64
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: publish
path: publish/
- name: Create Release
id: create_release
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
- name: Upload Release Assets
id: upload-release-assets
uses: actions/upload-release-asset@v1
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: |
./publish/win-x64/fdup.exe
./publish/win-x86/fdup.exe
./publish/linux-x64/fdup
./publish/osx-x64/fdup
asset_name: |
fdup-${{ steps.get_version.outputs.VERSION }}-win-x64.exe
fdup-${{ steps.get_version.outputs.VERSION }}-win-x86.exe
fdup-${{ steps.get_version.outputs.VERSION }}-linux_x64
fdup-${{ steps.get_version.outputs.VERSION }}-macos_x64
asset_content_type: application/octet-stream
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>fdup</AssemblyName>
<VersionPrefix>1.2.0</VersionPrefix>
<VersionPrefix>1.1.0</VersionPrefix>
<Authors>Oliver Booth</Authors>
</PropertyGroup>

View File

@ -1,4 +1,6 @@
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using Spectre.Console;
@ -8,7 +10,7 @@ namespace FindDuplicates;
internal sealed class ListCommand : AsyncCommand<ListSettings>
{
private readonly ConcurrentDictionary<string, ConcurrentBag<FileInfo>> _fileHashMap = new();
private readonly ConcurrentDictionary<string, List<FileInfo>> _fileHashMap = new();
public override async Task<int> ExecuteAsync(CommandContext context, ListSettings settings)
{
@ -29,7 +31,7 @@ internal sealed class ListCommand : AsyncCommand<ListSettings>
AnsiConsole.WriteLine();
int duplicates = 0;
foreach ((string hash, ConcurrentBag<FileInfo> files) in _fileHashMap)
foreach ((string hash, List<FileInfo> files) in _fileHashMap)
{
int fileCount = files.Count;
@ -89,7 +91,18 @@ internal sealed class ListCommand : AsyncCommand<ListSettings>
if (relativePath != ".")
AnsiConsole.MarkupLineInterpolated($"Searching [cyan]{relativePath}[/]");
AddChildDirectories(settings, currentDirectory, directoryStack);
if (settings.Recursive)
{
try
{
foreach (DirectoryInfo childDirectory in currentDirectory.EnumerateDirectories())
directoryStack.Push(childDirectory);
}
catch (Exception ex)
{
AnsiConsole.MarkupLineInterpolated($"[red]Error:[/] {ex.Message}");
}
}
try
{
@ -97,7 +110,7 @@ internal sealed class ListCommand : AsyncCommand<ListSettings>
{
string relativeFilePath = Path.GetRelativePath(inputDirectory.FullName, file.FullName);
AnsiConsole.MarkupLineInterpolated($"Checking hash for [cyan]{relativeFilePath}[/]");
tasks.Add(Task.Run(() => ProcessFile(file, settings)));
tasks.Add(Task.Run(() => ProcessFile(file)));
}
}
catch (Exception ex)
@ -107,7 +120,7 @@ internal sealed class ListCommand : AsyncCommand<ListSettings>
}
}
private void ProcessFile(FileInfo file, ListSettings settings)
private void ProcessFile(FileInfo file)
{
Span<byte> buffer = stackalloc byte[64];
try
@ -116,27 +129,13 @@ internal sealed class ListCommand : AsyncCommand<ListSettings>
using BufferedStream bufferedStream = new BufferedStream(stream, 1048576 /* 1MB */);
SHA512.HashData(bufferedStream, buffer);
string hash = ByteSpanToString(buffer);
if (settings.Verbose)
AnsiConsole.WriteLine($"{file.FullName} ->\n {hash}");
Trace.WriteLine($"{file.FullName}: {hash}");
ConcurrentBag<FileInfo> cache = _fileHashMap.GetOrAdd(hash, _ => []);
cache.Add(file);
}
catch (Exception ex)
{
AnsiConsole.MarkupLineInterpolated($"[red]Error:[/] {ex.Message}");
}
}
if (!_fileHashMap.TryGetValue(hash, out List<FileInfo>? cache))
_fileHashMap[hash] = cache = new List<FileInfo>();
private static void AddChildDirectories(ListSettings settings, DirectoryInfo directory, Stack<DirectoryInfo> stack)
{
if (!settings.Recursive)
return;
try
{
foreach (DirectoryInfo childDirectory in directory.EnumerateDirectories())
stack.Push(childDirectory);
lock (cache)
cache.Add(file);
}
catch (Exception ex)
{

View File

@ -5,18 +5,12 @@ namespace FindDuplicates;
internal sealed class ListSettings : CommandSettings
{
[CommandArgument(0, "[path]")]
[Description("The path to search. Defaults to the current directory.")]
[DefaultValue(".")]
public string InputPath { get; set; } = ".";
[CommandArgument(0, "<path>")]
[Description("The path to search.")]
public string InputPath { get; set; } = string.Empty;
[CommandOption("-r|--recursive")]
[Description("When this flag is set, the directory will be scanned recursively. This may take longer.")]
[DefaultValue(false)]
public bool Recursive { get; set; } = false;
[CommandOption("--verbose")]
[Description("Enable verbose output.")]
[DefaultValue(false)]
public bool Verbose { get; set; } = false;
}