in JetBrains.Profiler.SelfApi/src/Impl/PrerequisiteBase.cs [65:203]
private async Task DoDownloadAsync(
Uri nugetUrl,
NuGetApi nugetApi,
string downloadTo,
IProgress<double> progress,
CancellationToken cancellationToken)
{
const double downloadWeight = 0.8;
const double unzipWeight = 1.0 - downloadWeight;
try
{
if (string.IsNullOrEmpty(downloadTo))
downloadTo = GetDefaultDownloadPath();
Trace.Info("Prerequisite.Download: targetPath = `{0}`", downloadTo);
Directory.CreateDirectory(downloadTo);
// Note(ww898): We force the OS architecture everywhere!!! Process architecture is inherited by default in macOS ARM64. We turn off this behavior for x64 processes with /usr/bin/arch!!!
var runtimeIdString = HabitatInfo.OSRuntimeIdString;
var nupkgName = GetPackageName() + "." + runtimeIdString;
string nupkgFolder, nupkgPath, readyMarker;
var downloadProgress = new SubProgress(progress, 0, downloadWeight);
var unzipProgress = new SubProgress(progress, downloadWeight * 100.0, unzipWeight);
using (var http = new HttpClient())
{
Trace.Verbose("Prerequisite.Download: Requesting...");
var content = await http
.GetNupkgContentAsync(nugetUrl, nugetApi, nupkgName, SemanticVersion, cancellationToken)
.ConfigureAwait(false);
var latestVersion = content.Headers.GetValues("Version").Single();
nupkgFolder = Path.Combine(downloadTo, Name, latestVersion, runtimeIdString);
readyMarker = Path.Combine(nupkgFolder, ".ready");
if (File.Exists(readyMarker) && TryGetDownloadedRunner(downloadTo, runtimeIdString, out _runnerPath))
{
Trace.Verbose("Prerequisite.Download: Package version `{0}` already downloaded.", latestVersion);
return;
}
Directory.CreateDirectory(nupkgFolder);
nupkgPath = Path.Combine(nupkgFolder, $"{nupkgName}.{latestVersion}.nupkg");
Trace.Verbose("Prerequisite.Download: Saving...");
using (var input = await content.ReadAsStreamAsync().ConfigureAwait(false))
using (var output = File.Create(nupkgPath))
{
CopyStream(
input,
output,
content.Headers.ContentLength ?? GetEstimatedSize(),
downloadProgress,
cancellationToken
);
}
}
const string toolsPrefix = "tools/";
Trace.Verbose("Prerequisite.Download: Reading .nupkg ...");
using (var zipInput = File.OpenRead(nupkgPath))
using (var nupkg = new ZipArchive(zipInput))
{
var toolsEntries = nupkg.Entries
.Where(x => x.FullName.StartsWith(toolsPrefix, StringComparison.OrdinalIgnoreCase))
.ToArray();
if (toolsEntries.Length == 0)
throw new InvalidOperationException(
"Something went wrong: unable to find /tools folder inside NuGet package.");
var totalLength = toolsEntries.Sum(x => x.Length);
Trace.Verbose(
"Prerequisite.Download: Found {0} entries of total length {1} bytes.",
toolsEntries.Length,
totalLength
);
Trace.Verbose("Prerequisite.Download: Unpacking...");
var totalUnzippedSize = 0L;
foreach (var entry in toolsEntries)
{
var dstPath = Path.Combine(nupkgFolder, entry.FullName.Substring(toolsPrefix.Length));
Directory.CreateDirectory(Path.GetDirectoryName(dstPath));
using (var input = entry.Open())
using (var output = File.Create(dstPath))
{
Trace.Verbose("Prerequisite.Download: `{0}` -> `{1}`", entry.FullName, dstPath);
CopyStream(
input,
output,
entry.Length,
new SubProgress(unzipProgress, 100.0 * totalUnzippedSize / totalLength, 1.0 * entry.Length / totalLength),
cancellationToken
);
}
if (HabitatInfo.Platform != JetPlatform.Windows)
{
Trace.Verbose("Setting up executable bit for {0}...", dstPath);
Helper.ChModExecutable(dstPath);
}
totalUnzippedSize += entry.Length;
}
}
Trace.Verbose("Prerequisite.Download: Cleaning up...");
File.Delete(nupkgPath);
if(!TryGetDownloadedRunner(downloadTo, runtimeIdString, out _runnerPath))
throw new InvalidOperationException($"Something went wrong: the {Name} console profiler not found.");
new FileStream(readyMarker, FileMode.Create).Dispose();
Trace.Verbose("Prerequisite.Download: Confirmed everything is ready to use.");
}
catch (HttpRequestException e)
{
throw new Exception(
$"Failed to download prerequisite package. Please, check the NuGet URL and Internet connection.\n[{nugetUrl}]",
e
);
}
catch (IOException e)
{
ThrowOperationCanceledExceptionIfNeeded(e);
throw new Exception(
$"Failed to save/unpack prerequisite package. Please, check the path and available disk space.\n[{downloadTo}]",
e
);
}
}