(feature): added TryCreateTarFromDirectory extension method

This commit is contained in:
Maksym Sadovnychyy 2025-05-15 15:07:34 +02:00
parent cbdce549c1
commit 926cebcdc0
4 changed files with 240 additions and 1 deletions

View File

@ -504,6 +504,88 @@ This utility makes it easy to compose complex logical expressions dynamically, a
---
### FormatsExtensions
The `FormatsExtensions` class in the `MaksIT.Core.Extensions` namespace provides utility methods for working with TAR file creation from directories. These methods simplify the process of compressing directories into TAR files while handling various edge cases, such as invalid paths or empty directories.
---
#### Methods
##### 1. **`TryCreateTarFromDirectory`**
###### Summary
Attempts to create a TAR file from the contents of a specified directory. Returns `true` if the operation succeeds, or `false` if it fails due to invalid input or other errors.
###### Parameters
- `string sourceDirectory`: The path to the source directory to be compressed.
- `string outputTarPath`: The path where the TAR file will be created.
###### Usage
```csharp
string sourceDirectory = @"C:\MyFolder";
string outputTarPath = @"C:\MyFolder.tar";
if (FormatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath)) {
Console.WriteLine("TAR file created successfully.");
}
else {
Console.WriteLine("Failed to create TAR file.");
}
```
---
#### Features
1. **Error Handling**:
- Returns `false` for invalid source directories, empty directories, or inaccessible output paths.
2. **Cross-Platform Compatibility**:
- Designed to work on platforms supported by .NET 8.
3. **Ease of Use**:
- Simplifies the process of creating TAR files with minimal code.
---
#### Notes
- **Use Cases**:
- Archiving directories for backup or distribution.
- Automating file compression tasks in applications.
- **Edge Cases**:
- If the source directory does not exist, is empty, or the output path is invalid, the method will return `false`.
- If the output file is locked or cannot be created, the method will also return `false`.
---
#### Example End-to-End Usage
```csharp
// Valid input
string sourceDirectory = @"C:\MyFolder";
string outputTarPath = @"C:\MyFolder.tar";
if (FormatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath)) {
Console.WriteLine("TAR file created successfully.");
}
else {
Console.WriteLine("Failed to create TAR file.");
}
// Invalid source directory
string invalidSourceDirectory = @"C:\NonExistentFolder";
if (!FormatsExtensions.TryCreateTarFromDirectory(invalidSourceDirectory, outputTarPath)) {
Console.WriteLine("Source directory does not exist.");
}
```
---
### GuidExtensions
The `GuidExtensions` class in the `MaksIT.Core.Extensions` namespace provides an extension method for converting a `Guid` to a nullable `Guid?`. This is useful in scenarios where the default value of `Guid.Empty` needs to be treated as `null`.

View File

@ -0,0 +1,98 @@

namespace MaksIT.Core.Extensions.Tests;
public class FromatsExtensionsTests {
[Fact]
public void TryCreateTarFromDirectory_InvalidSourceDirectory_ReturnsFalse() {
// Arrange
string invalidSourceDirectory = "NonExistentDirectory";
string outputTarPath = "output.tar";
// Act
bool result = FromatsExtensions.TryCreateTarFromDirectory(invalidSourceDirectory, outputTarPath);
// Assert
Assert.False(result);
}
[Fact]
public void TryCreateTarFromDirectory_InvalidOutputPath_ReturnsFalse() {
// Arrange
string sourceDirectory = Path.GetTempPath();
string invalidOutputPath = "";
// Act
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, invalidOutputPath);
// Assert
Assert.False(result);
}
[Fact]
public void TryCreateTarFromDirectory_EmptySourceDirectory_ReturnsFalse() {
// Arrange
string sourceDirectory = Path.Combine(Path.GetTempPath(), "EmptyDirectory");
Directory.CreateDirectory(sourceDirectory); // Ensure the directory exists but is empty
string outputTarPath = Path.Combine(Path.GetTempPath(), "output.tar");
// Act
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
// Assert
Assert.False(result);
// Cleanup
Directory.Delete(sourceDirectory);
}
[Fact]
public void TryCreateTarFromDirectory_ValidInput_CreatesTarFile() {
// Arrange
string sourceDirectory = Path.Combine(Path.GetTempPath(), "TestDirectory");
Directory.CreateDirectory(sourceDirectory);
string testFilePath = Path.Combine(sourceDirectory, "test.txt");
File.WriteAllText(testFilePath, "Test content");
string outputTarPath = Path.Combine(Path.GetTempPath(), "output.tar");
// Act
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
// Assert
Assert.True(result);
Assert.True(File.Exists(outputTarPath));
// Cleanup
File.Delete(testFilePath);
Directory.Delete(sourceDirectory);
File.Delete(outputTarPath);
}
[Fact]
public void TryCreateTarFromDirectory_CannotCreateOutputFile_ReturnsFalse() {
// Arrange
string sourceDirectory = Path.Combine(Path.GetTempPath(), "TestDirectory");
Directory.CreateDirectory(sourceDirectory);
string testFilePath = Path.Combine(sourceDirectory, "test.txt");
File.WriteAllText(testFilePath, "Test content");
string outputTarPath = Path.Combine(Path.GetTempPath(), "output.tar");
// Lock the file to simulate inability to create it
using (FileStream lockedFile = File.Create(outputTarPath)) {
// Act
bool result = FromatsExtensions.TryCreateTarFromDirectory(sourceDirectory, outputTarPath);
// Assert
Assert.False(result);
}
// Cleanup
File.Delete(testFilePath);
Directory.Delete(sourceDirectory);
if (File.Exists(outputTarPath)) {
File.Delete(outputTarPath);
}
}
}

View File

@ -0,0 +1,59 @@
using System.Formats.Tar;
namespace MaksIT.Core.Extensions;
public static class FromatsExtensions {
public static bool TryCreateTarFromDirectory(string sourceDirectory, string outputTarPath) {
// Validate source directory
if (string.IsNullOrWhiteSpace(sourceDirectory) || !Directory.Exists(sourceDirectory)) {
return false;
}
// Validate output path
if (string.IsNullOrWhiteSpace(outputTarPath)) {
return false;
}
// Ensure the parent directory of the output file exists
string? outputDirectory = Path.GetDirectoryName(outputTarPath);
if (outputDirectory is not null && !Directory.Exists(outputDirectory)) {
try {
Directory.CreateDirectory(outputDirectory);
}
catch {
return false; // Return false if directory creation fails
}
}
// Validate if the source directory contains files
var files = Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories);
if (!files.Any()) {
return false;
}
// Create the TAR file
if (!CanCreateFile(outputTarPath)) {
return false; // Ensure the output file can be created
}
using FileStream fs = File.Create(outputTarPath);
using TarWriter writer = new TarWriter(fs, TarEntryFormat.Pax, leaveOpen: false);
foreach (string filePath in files) {
string relativePath = Path.GetRelativePath(sourceDirectory, filePath).Replace(Path.DirectorySeparatorChar, '/');
writer.WriteEntry(filePath, relativePath);
}
return true;
}
private static bool CanCreateFile(string filePath) {
try {
using (FileStream fs = File.Create(filePath, 1, FileOptions.DeleteOnClose)) { }
return true;
}
catch {
return false; // Return false if the file cannot be created
}
}
}

View File

@ -8,7 +8,7 @@
<!-- NuGet package metadata -->
<PackageId>MaksIT.Core</PackageId>
<Version>1.3.7</Version>
<Version>1.3.8</Version>
<Authors>Maksym Sadovnychyy</Authors>
<Company>MAKS-IT</Company>
<Product>MaksIT.Core</Product>