Skip to content
Open
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
10 changes: 7 additions & 3 deletions StabilityMatrix.Avalonia/Helpers/UnixPrerequisiteHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -559,12 +559,16 @@ public async Task InstallNodeIfNecessary(IProgress<ProgressReport>? progress = n
)
);

// unzip
await ArchiveHelper.Extract7ZAuto(nodeDownloadPath, AssetsDir);

var nodeDir = Compat.IsMacOS
? AssetsDir.JoinDir("node-v20.19.3-darwin-arm64")
: AssetsDir.JoinDir("node-v20.19.3-linux-x64");

// Node's tarball contains relative symlinks from bin/ into lib/ (e.g. bin/npm -> ../lib/...).
// Bundled 7-Zip 26.01's default symlink checks reject these ../lib links, regardless of filesystem.
// -snld6 was the lowest level that accepted them in testing, so relax the check for this archive only.
// A filesystem that cannot create symlinks (e.g. exFAT) may still fail independently.
await ArchiveHelper.Extract7ZTar(nodeDownloadPath, AssetsDir, symlinkSecurityLevel: 6);

Directory.Move(nodeDir, NodeDir);

progress?.Report(
Expand Down
62 changes: 39 additions & 23 deletions StabilityMatrix.Core/Helper/ArchiveHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,20 @@ public static async Task AddToArchive7Z(string archivePath, string sourceDirecto
result.EnsureSuccessExitCode();
}

public static async Task<ArchiveInfo> Extract7Z(string archivePath, string extractDirectory)
public static async Task<ArchiveInfo> Extract7Z(
string archivePath,
string extractDirectory,
int? symlinkSecurityLevel = null
)
{
var args = $"x {ProcessRunner.Quote(archivePath)} -o{ProcessRunner.Quote(extractDirectory)} -y";
if (symlinkSecurityLevel is < 0 or > 20)
{
throw new ArgumentOutOfRangeException(nameof(symlinkSecurityLevel), "Must be between 0 and 20.");
}

var symlinkSecuritySwitch = symlinkSecurityLevel is { } level ? $" -snld{level}" : string.Empty;
var args =
$"x {ProcessRunner.Quote(archivePath)} -o{ProcessRunner.Quote(extractDirectory)} -y{symlinkSecuritySwitch}";

var result = await ProcessRunner
.GetProcessResultAsync(SevenZipPath, args)
Expand Down Expand Up @@ -176,7 +187,11 @@ public static async Task<ArchiveInfo> Extract7Z(
/// <param name="archivePath"></param>
/// <param name="extractDirectory"></param>
/// <returns></returns>
public static async Task<ArchiveInfo> Extract7ZTar(string archivePath, string extractDirectory)
public static async Task<ArchiveInfo> Extract7ZTar(
string archivePath,
string extractDirectory,
int? symlinkSecurityLevel = null
)
{
if (!archivePath.EndsWith(".tar.gz"))
{
Expand All @@ -194,7 +209,7 @@ public static async Task<ArchiveInfo> Extract7ZTar(string archivePath, string ex

try
{
return await Extract7Z(tarPath, extractDirectory).ConfigureAwait(false);
return await Extract7Z(tarPath, extractDirectory, symlinkSecurityLevel).ConfigureAwait(false);
}
finally
{
Expand Down Expand Up @@ -251,7 +266,7 @@ public static async Task Extract(
var progressMonitor = progress switch
{
null => null,
_ => new Timer(TimeSpan.FromMilliseconds(36))
_ => new Timer(TimeSpan.FromMilliseconds(36)),
};

if (progressMonitor != null)
Expand All @@ -264,28 +279,29 @@ public static async Task Extract(
};
}

await Task.Factory.StartNew(
() =>
{
var extractOptions = new ExtractionOptions { Overwrite = true, ExtractFullPath = true, };
using var stream = File.OpenRead(archivePath);
using var archive = ReaderFactory.Open(stream);
await Task
.Factory.StartNew(
() =>
{
var extractOptions = new ExtractionOptions { Overwrite = true, ExtractFullPath = true };
using var stream = File.OpenRead(archivePath);
using var archive = ReaderFactory.Open(stream);

// Start the progress reporting timer
progressMonitor?.Start();
// Start the progress reporting timer
progressMonitor?.Start();

while (archive.MoveToNextEntry())
{
var entry = archive.Entry;
if (!entry.IsDirectory)
while (archive.MoveToNextEntry())
{
count += (ulong)entry.CompressedSize;
var entry = archive.Entry;
if (!entry.IsDirectory)
{
count += (ulong)entry.CompressedSize;
}
archive.WriteEntryToDirectory(outputDirectory, extractOptions);
}
archive.WriteEntryToDirectory(outputDirectory, extractOptions);
}
},
TaskCreationOptions.LongRunning
)
},
TaskCreationOptions.LongRunning
)
.ConfigureAwait(false);

progress?.Report(new ProgressReport(progress: 1, message: "Done extracting"));
Expand Down
Loading