2022-04-14 16:20:25 -05:00
|
|
|
// Licensed to the .NET Foundation under one or more agreements.
|
|
|
|
// The .NET Foundation licenses this file to you under the MIT license.
|
|
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
2023-06-02 15:24:47 -05:00
|
|
|
using Microsoft.Extensions.FileSystemGlobbing;
|
2022-04-14 16:20:25 -05:00
|
|
|
using System;
|
2023-06-02 15:24:47 -05:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Formats.Tar;
|
|
|
|
using System.IO;
|
|
|
|
using System.IO.Compression;
|
2022-04-14 16:20:25 -05:00
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Xunit.Abstractions;
|
|
|
|
|
|
|
|
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
|
|
|
|
|
|
|
|
public static class Utilities
|
|
|
|
{
|
2023-06-08 09:00:41 +02:00
|
|
|
public static void ExtractTarball(string tarballPath, string outputDir, ITestOutputHelper outputHelper)
|
2023-06-02 15:24:47 -05:00
|
|
|
{
|
2023-06-08 09:00:41 +02:00
|
|
|
// TarFile doesn't properly handle hard links (https://github.com/dotnet/runtime/pull/85378#discussion_r1221817490),
|
|
|
|
// use 'tar' instead.
|
|
|
|
ExecuteHelper.ExecuteProcessValidateExitCode("tar", $"xzf {tarballPath} -C {outputDir}", outputHelper);
|
2023-06-02 15:24:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void ExtractTarball(string tarballPath, string outputDir, string targetFilePath)
|
|
|
|
{
|
|
|
|
Matcher matcher = new();
|
|
|
|
matcher.AddInclude(targetFilePath);
|
|
|
|
|
|
|
|
using FileStream fileStream = File.OpenRead(tarballPath);
|
|
|
|
using GZipStream decompressorStream = new(fileStream, CompressionMode.Decompress);
|
|
|
|
using TarReader reader = new(decompressorStream);
|
|
|
|
|
|
|
|
TarEntry entry;
|
|
|
|
while ((entry = reader.GetNextEntry()) is not null)
|
|
|
|
{
|
|
|
|
if (matcher.Match(entry.Name).HasMatches)
|
|
|
|
{
|
|
|
|
string outputPath = Path.Join(outputDir, entry.Name);
|
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
|
|
|
|
|
|
|
|
using FileStream outputFileStream = File.Create(outputPath);
|
|
|
|
entry.DataStream.CopyTo(outputFileStream);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static IEnumerable<string> GetTarballContentNames(string tarballPath)
|
|
|
|
{
|
|
|
|
using FileStream fileStream = File.OpenRead(tarballPath);
|
|
|
|
using GZipStream decompressorStream = new(fileStream, CompressionMode.Decompress);
|
|
|
|
using TarReader reader = new(decompressorStream);
|
|
|
|
|
|
|
|
TarEntry entry;
|
|
|
|
while ((entry = reader.GetNextEntry()) is not null)
|
|
|
|
{
|
|
|
|
yield return entry.Name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-14 16:20:25 -05:00
|
|
|
public static async Task RetryAsync(Func<Task> executor, ITestOutputHelper outputHelper)
|
|
|
|
{
|
|
|
|
await Utilities.RetryAsync(
|
|
|
|
async () =>
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
await executor();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
outputHelper);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static async Task RetryAsync(Func<Task<Exception?>> executor, ITestOutputHelper outputHelper)
|
|
|
|
{
|
|
|
|
const int maxRetries = 5;
|
|
|
|
const int waitFactor = 5;
|
|
|
|
|
|
|
|
int retryCount = 0;
|
|
|
|
|
|
|
|
Exception? exception = await executor();
|
|
|
|
while (exception != null)
|
|
|
|
{
|
|
|
|
retryCount++;
|
|
|
|
if (retryCount >= maxRetries)
|
|
|
|
{
|
|
|
|
throw new InvalidOperationException($"Failed after {retryCount} retries.", exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
int waitTime = Convert.ToInt32(Math.Pow(waitFactor, retryCount - 1));
|
|
|
|
if (outputHelper != null)
|
|
|
|
{
|
|
|
|
outputHelper.WriteLine($"Retry {retryCount}/{maxRetries}, retrying in {waitTime} seconds...");
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread.Sleep(TimeSpan.FromSeconds(waitTime));
|
|
|
|
exception = await executor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|