diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6fb9aba..4af54a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,10 +19,10 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - - name: Install .NET 7 SDK + - name: Install .NET SDK uses: actions/setup-dotnet@v1 with: - dotnet-version: '7.0.x' + dotnet-version: '8.0.x' # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Checkout Repository diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9f48385..40969e1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,7 +15,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v2 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore diff --git a/src/Extensions/CopyAndMoveExtensions.cs b/src/Extensions/CopyAndMoveExtensions.cs index 294fa1e..6bc1e1f 100644 --- a/src/Extensions/CopyAndMoveExtensions.cs +++ b/src/Extensions/CopyAndMoveExtensions.cs @@ -21,24 +21,28 @@ public static async Task CreateCopyOfAsync(this IModifiableFolder de { static async Task CreateCopyOfFallbackAsync(IModifiableFolder destinationFolder, IFile fileToCopy, bool overwrite, CancellationToken cancellationToken = default) { - // Open the source file - using var sourceStream = await fileToCopy.OpenStreamAsync(FileAccess.Read, cancellationToken: cancellationToken); - - // Create the destination file - var newFile = await destinationFolder.CreateFileAsync(fileToCopy.Name, overwrite, cancellationToken); - using var destinationStream = await newFile.OpenStreamAsync(FileAccess.ReadWrite, cancellationToken: cancellationToken); cancellationToken.ThrowIfCancellationRequested(); - // Align stream positions (if possible) - if (destinationStream.CanSeek && destinationStream.Position != 0) - destinationStream.Seek(0, SeekOrigin.Begin); + // If the destination file exists and overwrite is false, it shouldn't be overwritten or returned as-is. Throw an exception instead. + if (!overwrite) + { + try + { + var existing = await destinationFolder.GetFirstByNameAsync(fileToCopy.Name, cancellationToken); + if (existing is not null) + throw new FileAlreadyExistsException(fileToCopy.Name); + } + catch (FileNotFoundException) { } + } - if (sourceStream.CanSeek && sourceStream.Position != 0) - sourceStream.Seek(0, SeekOrigin.Begin); + // Create the destination file. + // 'overwrite: false' would have thrown above if the file exists, so either overwrite is already true or the file doesn't exist yet. + // Always overwrite here so the file is empty. + var newFile = await destinationFolder.CreateFileAsync(fileToCopy.Name, overwrite: true, cancellationToken); + using var destinationStream = await newFile.OpenStreamAsync(FileAccess.Write, cancellationToken: cancellationToken); - // Set stream length to zero to clear any existing data. - // Otherwise, writing less bytes than already exists would leave extra bytes at the end. - destinationStream.SetLength(0); + // Open the source file + using var sourceStream = await fileToCopy.OpenStreamAsync(FileAccess.Read, cancellationToken: cancellationToken); // Copy the src into the dest file await sourceStream.CopyToAsync(destinationStream, bufferSize: 81920, cancellationToken); @@ -47,18 +51,6 @@ static async Task CreateCopyOfFallbackAsync(IModifiableFolder destin } cancellationToken.ThrowIfCancellationRequested(); - - // If the destination file exists and overwrite is false, it shouldn't be overwritten or returned as-is. Throw an exception instead. - if (!overwrite) - { - try - { - var existing = await destinationFolder.GetFirstByNameAsync(fileToCopy.Name, cancellationToken); - if (existing is not null) - throw new FileAlreadyExistsException(fileToCopy.Name); - } - catch (FileNotFoundException) { } - } // If the destination folder declares a non-fallback copy path, try that. // Provide fallback in case this file is not a handled type. diff --git a/src/Memory/MemoryFile.cs b/src/Memory/MemoryFile.cs index 5283274..fa3243c 100644 --- a/src/Memory/MemoryFile.cs +++ b/src/Memory/MemoryFile.cs @@ -56,6 +56,7 @@ public Task OpenStreamAsync(FileAccess accessMode = FileAccess.Read, Can if (accessMode == 0) throw new ArgumentOutOfRangeException(nameof(accessMode), $"{nameof(FileAccess)}.{accessMode} is not valid here."); + _memoryStream.Position = 0; return Task.FromResult(new NonDisposableStreamWrapper(_memoryStream)); } } diff --git a/src/System/IO/SystemFolder.cs b/src/System/IO/SystemFolder.cs index 41a2b2a..4d2b351 100644 --- a/src/System/IO/SystemFolder.cs +++ b/src/System/IO/SystemFolder.cs @@ -246,18 +246,18 @@ public async Task CreateCopyOfAsync(IFile fileToCopy, bool overwrite // Handle using System.IO var newPath = global::System.IO.Path.Combine(Path, systemFile.Name); - // If the source and destination are the same, there's no need to copy. - if (systemFile.Path == newPath) - return new SystemFile(newPath); - if (File.Exists(newPath)) { if (!overwrite) - return new SystemFile(newPath, noValidation: true); + throw new FileAlreadyExistsException(fileToCopy.Name); File.Delete(newPath); } + // If the source and destination are the same, there's no need to copy. + if (systemFile.Path == newPath) + return systemFile; + File.Copy(systemFile.Path, newPath, overwrite); return new SystemFile(newPath, noValidation: true); diff --git a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/InMemIFileTests.cs b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveEntryFile_FileInMemory_Tests.cs similarity index 94% rename from tests/OwlCore.Storage.Tests/Archive/ZipArchive/InMemIFileTests.cs rename to tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveEntryFile_FileInMemory_Tests.cs index 162a0fb..7a44f5c 100644 --- a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/InMemIFileTests.cs +++ b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveEntryFile_FileInMemory_Tests.cs @@ -9,7 +9,7 @@ namespace OwlCore.Storage.Tests.Archive.ZipArchive; /// A test suite for s created entirely in memory. /// [TestClass] -public class InMemIFileTests : CommonIFileTests +public class ZipArchiveEntryFile_FileInMemory_Tests : CommonIFileTests { // Required for base class to perform common tests. public override Task CreateFileAsync() diff --git a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/IFileTests.cs b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveEntryFile_FileOnDisk_Tests.cs similarity index 95% rename from tests/OwlCore.Storage.Tests/Archive/ZipArchive/IFileTests.cs rename to tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveEntryFile_FileOnDisk_Tests.cs index a0929fb..334e097 100644 --- a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/IFileTests.cs +++ b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveEntryFile_FileOnDisk_Tests.cs @@ -6,7 +6,7 @@ namespace OwlCore.Storage.Tests.Archive.ZipArchive; [TestClass] -public class IFileTests : CommonIFileTests +public class ZipArchiveEntryFile_FileOnDisk_Tests : CommonIFileTests { // Required for base class to perform common tests. public override async Task CreateFileAsync() diff --git a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/InMemIFolderTests.cs b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveFolder_FileInMemory_Tests.cs similarity index 98% rename from tests/OwlCore.Storage.Tests/Archive/ZipArchive/InMemIFolderTests.cs rename to tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveFolder_FileInMemory_Tests.cs index 06a5b00..1fbb6db 100644 --- a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/InMemIFolderTests.cs +++ b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveFolder_FileInMemory_Tests.cs @@ -9,7 +9,7 @@ namespace OwlCore.Storage.Tests.Archive.ZipArchive; /// A test suite for s created entirely in memory. /// [TestClass] -public class InMemIFolderTests : CommonIModifiableFolderTests +public class ZipArchiveFolder_FileInMemory_Tests : CommonIModifiableFolderTests { // Required for base class to perform common tests. public override Task CreateModifiableFolderAsync() diff --git a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/IFolderTests.cs b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveFolder_FileOnDisk_Tests.cs similarity index 83% rename from tests/OwlCore.Storage.Tests/Archive/ZipArchive/IFolderTests.cs rename to tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveFolder_FileOnDisk_Tests.cs index a79b884..699f998 100644 --- a/tests/OwlCore.Storage.Tests/Archive/ZipArchive/IFolderTests.cs +++ b/tests/OwlCore.Storage.Tests/Archive/ZipArchive/ZipArchiveFolder_FileOnDisk_Tests.cs @@ -6,13 +6,13 @@ namespace OwlCore.Storage.Tests.Archive.ZipArchive; [TestClass] -public class IFolderTests : CommonIModifiableFolderTests +public class ZipArchiveFolder_FileOnDisk_Tests : CommonIModifiableFolderTests { // Required for base class to perform common tests. - public override async Task CreateModifiableFolderAsync() + public override Task CreateModifiableFolderAsync() { var sourceFile = new SystemFile(CreateEmptyArchiveOnDisk()); - return new ZipArchiveFolder(sourceFile); + return Task.FromResult(new ZipArchiveFolder(sourceFile)); } public override async Task CreateModifiableFolderWithItems(int fileCount, int folderCount) diff --git a/tests/OwlCore.Storage.Tests/Memory/IFileTests.cs b/tests/OwlCore.Storage.Tests/Memory/MemoryFileTests.cs similarity index 100% rename from tests/OwlCore.Storage.Tests/Memory/IFileTests.cs rename to tests/OwlCore.Storage.Tests/Memory/MemoryFileTests.cs diff --git a/tests/OwlCore.Storage.Tests/Memory/IFolderTests.cs b/tests/OwlCore.Storage.Tests/Memory/MemoryFolderTests.cs similarity index 93% rename from tests/OwlCore.Storage.Tests/Memory/IFolderTests.cs rename to tests/OwlCore.Storage.Tests/Memory/MemoryFolderTests.cs index 276f7cc..d787199 100644 --- a/tests/OwlCore.Storage.Tests/Memory/IFolderTests.cs +++ b/tests/OwlCore.Storage.Tests/Memory/MemoryFolderTests.cs @@ -4,7 +4,7 @@ namespace OwlCore.Storage.Tests.Memory; [TestClass] -public class IFolderTests : CommonIModifiableFolderTests +public class MemoryFolderTests : CommonIModifiableFolderTests { // Required for base class to perform common tests. public override Task CreateModifiableFolderAsync() diff --git a/tests/OwlCore.Storage.Tests/OwlCore.Storage.Tests.csproj b/tests/OwlCore.Storage.Tests/OwlCore.Storage.Tests.csproj index 3bdec7d..e39f68b 100644 --- a/tests/OwlCore.Storage.Tests/OwlCore.Storage.Tests.csproj +++ b/tests/OwlCore.Storage.Tests/OwlCore.Storage.Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable diff --git a/tests/OwlCore.Storage.Tests/SystemIO/IFileTests.cs b/tests/OwlCore.Storage.Tests/SystemIO/SystemFileTests.cs similarity index 95% rename from tests/OwlCore.Storage.Tests/SystemIO/IFileTests.cs rename to tests/OwlCore.Storage.Tests/SystemIO/SystemFileTests.cs index 906f648..b53c521 100644 --- a/tests/OwlCore.Storage.Tests/SystemIO/IFileTests.cs +++ b/tests/OwlCore.Storage.Tests/SystemIO/SystemFileTests.cs @@ -4,7 +4,7 @@ namespace OwlCore.Storage.Tests.SystemIO; [TestClass] -public class IFileTests : CommonIFileTests +public class SystemFileTests : CommonIFileTests { // Required for base class to perform common tests. public override async Task CreateFileAsync() diff --git a/tests/OwlCore.Storage.Tests/SystemIO/IFolderTests.cs b/tests/OwlCore.Storage.Tests/SystemIO/SystemFolderTests.cs similarity index 97% rename from tests/OwlCore.Storage.Tests/SystemIO/IFolderTests.cs rename to tests/OwlCore.Storage.Tests/SystemIO/SystemFolderTests.cs index 5095032..b080028 100644 --- a/tests/OwlCore.Storage.Tests/SystemIO/IFolderTests.cs +++ b/tests/OwlCore.Storage.Tests/SystemIO/SystemFolderTests.cs @@ -4,7 +4,7 @@ namespace OwlCore.Storage.Tests.SystemIO; [TestClass] -public class IFolderTests : CommonIModifiableFolderTests +public class SystemFolderTests : CommonIModifiableFolderTests { public override Task CreateModifiableFolderAsync() {