generated from Nexus-Mods/NexusMods.App.Template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #56 from Nexus-Mods/nx-extra-extensions
Added: Extensions for Remaining High Level Nx APIs
- Loading branch information
Showing
3 changed files
with
207 additions
and
0 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
src/Extensions/NexusMods.Paths.Extensions.Nx/Extensions/NxPackerBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using JetBrains.Annotations; | ||
using NexusMods.Archives.Nx.Enums; | ||
using NexusMods.Archives.Nx.Packing; | ||
using NexusMods.Archives.Nx.Structs; | ||
using NexusMods.Paths.Extensions.Nx.FileProviders; | ||
namespace NexusMods.Paths.Extensions.Nx.Extensions; | ||
|
||
/// <summary> | ||
/// Extension methods for NxPackerBuilder to integrate AbsolutePath-based APIs. | ||
/// </summary> | ||
[PublicAPI] | ||
public static class NxPackerBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Adds a file to be packed using an <see cref="AbsolutePath"/>. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="NxPackerBuilder"/> instance.</param> | ||
/// <param name="absolutePath">The <see cref="AbsolutePath"/> of the file to add.</param> | ||
/// <param name="options">The options for adding the file.</param> | ||
/// <returns>The builder instance for method chaining.</returns> | ||
public static NxPackerBuilder AddFile(this NxPackerBuilder builder, AbsolutePath absolutePath, AddFileParams options) | ||
{ | ||
var packerFile = new PackerFile | ||
{ | ||
FileDataProvider = new FromAbsolutePathProvider | ||
{ | ||
FilePath = absolutePath | ||
}, | ||
RelativePath = options.RelativePath, | ||
FileSize = (long)absolutePath.FileInfo.Size.Value, | ||
SolidType = options.SolidType, | ||
CompressionPreference = options.CompressionPreference | ||
}; | ||
|
||
return builder.AddPackerFile(packerFile); | ||
} | ||
|
||
/// <summary> | ||
/// Sets the output (archive) to an <see cref="AbsolutePath"/>. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="NxPackerBuilder"/> instance.</param> | ||
/// <param name="outputPath">The <see cref="AbsolutePath"/> where the packed archive will be saved.</param> | ||
/// <returns>The builder instance for method chaining.</returns> | ||
public static NxPackerBuilder WithOutput(this NxPackerBuilder builder, AbsolutePath outputPath) | ||
{ | ||
var stream = outputPath.FileSystem.CreateFile(outputPath); | ||
return builder.WithOutput(stream); | ||
} | ||
|
||
/// <summary> | ||
/// Adds all files under a given folder to the output using <see cref="AbsolutePath"/>. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="NxPackerBuilder"/> instance.</param> | ||
/// <param name="folderPath">The <see cref="AbsolutePath"/> of the folder to add items from.</param> | ||
/// <param name="solidType">The solid type preference for the files.</param> | ||
/// <param name="compressionPreference">The compression preference for the files.</param> | ||
/// <returns>The builder instance for method chaining.</returns> | ||
public static NxPackerBuilder AddFolder(this NxPackerBuilder builder, | ||
AbsolutePath folderPath, | ||
SolidPreference solidType = SolidPreference.Default, | ||
CompressionPreference compressionPreference = CompressionPreference.NoPreference) | ||
{ | ||
foreach (var file in folderPath.EnumerateFiles()) | ||
{ | ||
var options = new AddFileParams | ||
{ | ||
RelativePath = file.RelativeTo(folderPath).ToString(), | ||
SolidType = solidType, | ||
CompressionPreference = compressionPreference | ||
}; | ||
|
||
builder.AddFile(file, options); | ||
} | ||
return builder; | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
src/Extensions/NexusMods.Paths.Extensions.Nx/Extensions/NxUnpackerBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
using JetBrains.Annotations; | ||
using NexusMods.Archives.Nx.Packing; | ||
using NexusMods.Archives.Nx.Packing.Unpack; | ||
using NexusMods.Paths.Extensions.Nx.FileProviders; | ||
namespace NexusMods.Paths.Extensions.Nx.Extensions; | ||
|
||
/// <summary> | ||
/// Extension methods for <see cref="NxUnpackerBuilder"/> to integrate <see cref="AbsolutePath"/>-based APIs. | ||
/// </summary> | ||
[PublicAPI] | ||
public static class NxUnpackerBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Creates an <see cref="NxUnpackerBuilder"/> instance using an AbsolutePath. | ||
/// </summary> | ||
/// <param name="archivePath">The <see cref="AbsolutePath"/> of the .nx archive file.</param> | ||
/// <param name="hasLotsOfFiles">Hint whether the archive contains lots of files (100+).</param> | ||
/// <returns>A new instance of <see cref="NxUnpackerBuilder"/>.</returns> | ||
public static NxUnpackerBuilder FromFile(AbsolutePath archivePath, bool hasLotsOfFiles = false) | ||
{ | ||
return new NxUnpackerBuilder(new FromAbsolutePathProvider | ||
{ | ||
FilePath = archivePath | ||
}, hasLotsOfFiles); | ||
} | ||
|
||
/// <summary> | ||
/// Extracts files to a specified directory using <see cref="AbsolutePath"/>. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="NxUnpackerBuilder"/> instance.</param> | ||
/// <param name="outputDirectory">The <see cref="AbsolutePath"/> of the directory to extract files to.</param> | ||
/// <param name="entries">The file entries to extract.</param> | ||
/// <returns>The builder instance for method chaining.</returns> | ||
public static NxUnpackerBuilder AddFilesWithFileSystemOutput(this NxUnpackerBuilder builder, AbsolutePath outputDirectory, PathedFileEntry[] entries) | ||
{ | ||
var outputProviders = new OutputAbsolutePathProvider[entries.Length]; | ||
for (var x = 0; x < entries.Length; x++) | ||
{ | ||
var entry = entries[x]; | ||
var outputPath = outputDirectory.Combine(entry.FilePath); | ||
outputProviders[x] = new OutputAbsolutePathProvider(outputPath, entry.FilePath, entry.Entry); | ||
} | ||
builder.Outputs.AddRange(outputProviders); | ||
return builder; | ||
} | ||
|
||
/// <summary> | ||
/// Extracts all files to a specified directory using AbsolutePath. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="NxUnpackerBuilder"/> instance.</param> | ||
/// <param name="outputDirectory">The <see cref="AbsolutePath"/> of the directory to extract files to.</param> | ||
/// <returns>The builder instance for method chaining.</returns> | ||
public static NxUnpackerBuilder AddAllFilesWithFileSystemOutput(this NxUnpackerBuilder builder, AbsolutePath outputDirectory) | ||
{ | ||
return builder.AddFilesWithFileSystemOutput(outputDirectory, builder.GetPathedFileEntries()); | ||
} | ||
|
||
/// <summary> | ||
/// Extracts a single file to a specified path using <see cref="AbsolutePath"/>. | ||
/// </summary> | ||
/// <param name="builder">The <see cref="NxUnpackerBuilder"/> instance.</param> | ||
/// <param name="entry">The file entry to extract.</param> | ||
/// <param name="outputPath">The <see cref="AbsolutePath"/> where the file should be extracted.</param> | ||
/// <returns>The builder instance for method chaining.</returns> | ||
public static NxUnpackerBuilder AddFileWithFileSystemOutput(this NxUnpackerBuilder builder, PathedFileEntry entry, AbsolutePath outputPath) | ||
{ | ||
// Output provider disposed during extract. | ||
builder.Outputs.Add(new OutputAbsolutePathProvider(outputPath, entry.FilePath, entry.Entry)); | ||
return builder; | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
tests/Extensions/NexusMods.Paths.Extensions.Nx.Tests/Extensions/NxBuilderExtensionsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using FluentAssertions; | ||
using NexusMods.Archives.Nx.Packing; | ||
using NexusMods.Paths.Extensions.Nx.Extensions; | ||
using NexusMods.Paths.TestingHelpers; | ||
using Xunit; | ||
namespace NexusMods.Paths.Extensions.Nx.Tests.Extensions; | ||
|
||
/// <summary> | ||
/// These tests are more of a 'sanity' check to ensure that our extensions | ||
/// integrate correctly with Nx. They don't have much substance, other than | ||
/// confirming that stuff 'just works'. | ||
/// </summary> | ||
public class NxBuilderExtensionsTests | ||
{ | ||
[Theory, AutoFileSystem] | ||
public async Task NxPackerBuilder_CanAddFolderFromIFileSystem_AndExtractToIFileSystem(InMemoryFileSystem fs, AbsolutePath folderPath) | ||
{ | ||
// Arrange | ||
var file1 = folderPath.Combine("file1.txt"); | ||
var file2 = folderPath.Combine("subfolder/file2.txt"); | ||
await fs.WriteAllTextAsync(file1, "Content 1"); | ||
await fs.WriteAllTextAsync(file2, "Content 2"); | ||
|
||
var builder = new NxPackerBuilder(); | ||
var outputPath = folderPath.Parent.Combine("output.nx"); | ||
|
||
// Act | ||
builder.AddFolder(folderPath) | ||
.WithOutput(outputPath) | ||
.Build(); | ||
|
||
// Assert | ||
fs.FileExists(outputPath).Should().BeTrue(); | ||
var unpacker = NxUnpackerBuilderExtensions.FromFile(outputPath); | ||
var entries = unpacker.GetPathedFileEntries(); | ||
entries.Should().HaveCount(2); | ||
entries.Should().Contain(e => e.FilePath == "file1.txt"); | ||
entries.Should().Contain(e => e.FilePath == "subfolder/file2.txt"); | ||
|
||
// Verify we can extract all files | ||
var extractFolder = folderPath.Parent.Combine("extracted"); | ||
unpacker.AddAllFilesWithFileSystemOutput(extractFolder).Extract(); | ||
|
||
var extractedFile1 = extractFolder.Combine("file1.txt"); | ||
var extractedFile2 = extractFolder.Combine("subfolder/file2.txt"); | ||
|
||
fs.FileExists(extractedFile1).Should().BeTrue(); | ||
fs.FileExists(extractedFile2).Should().BeTrue(); | ||
|
||
(await fs.ReadAllTextAsync(extractedFile1)).Should().Be("Content 1"); | ||
(await fs.ReadAllTextAsync(extractedFile2)).Should().Be("Content 2"); | ||
|
||
// Verify we can extract a single file. | ||
unpacker = NxUnpackerBuilderExtensions.FromFile(outputPath); | ||
var extractedFile1Copy = extractFolder.Combine("file1-copy.txt"); | ||
var file1Entry = entries.First(x => x.FilePath == "file1.txt"); | ||
unpacker.AddFileWithFileSystemOutput(file1Entry, extractedFile1Copy).Extract(); | ||
(await fs.ReadAllTextAsync(extractedFile1Copy)).Should().Be("Content 1"); | ||
} | ||
} |