Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workload manifest updates #16891

Merged
merged 8 commits into from
Apr 30, 2021
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ await Task.WhenAll(

if (!accumulativeSearchResults.Any())
{
_logger.LogWarning(
throw new Exception(
string.Format(
LocalizableStrings.FailedToLoadNuGetSourceSourceIsNotValid,
packageIdentifier,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.DotNet.Workloads.Workload.Install.InstallRecord;

namespace Microsoft.DotNet.Workloads.Workload.Install
{
internal interface IWorkloadManifestUpdater
sfoslund marked this conversation as resolved.
Show resolved Hide resolved
{
Task UpdateAdvertisingManifestsAsync(SdkFeatureBand featureBand, bool includePreviews);

IEnumerable<(ManifestId manifestId, ManifestVersion existingVersion, ManifestVersion newVersion)> CalculateManifestUpdates(SdkFeatureBand featureBand);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,22 @@
<data name="RollingBackPackInstall" xml:space="preserve">
<value>Rolling back pack {0} installation...</value>
</data>
<data name="AdManifestUpdated" xml:space="preserve">
<value>Updated advertising manifest {0}.</value>
</data>
<data name="FailedAdManifestUpdate" xml:space="preserve">
<value>Failed to update the advertising manifest {0}: {1}</value>
</data>
<data name="ManifestDoesNotExist" xml:space="preserve">
<value>No manifest with id {0} exists.</value>
</data>
<data name="FailedToInstallWorkloadManifest" xml:space="preserve">
<value>Failed to install manifest {0} version {1}: {2}.</value>
</data>
<data name="InstallingWorkloadManifest" xml:space="preserve">
<value>Installing workload manifest {0} version {1}.</value>
</data>
<data name="IncludePreviewOptionDescription" xml:space="preserve">
<value>Allow prerelease workload manifests.</value>
</data>
</root>
18 changes: 11 additions & 7 deletions src/Cli/dotnet/commands/dotnet-workload/install/ManifestVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,30 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using Microsoft.DotNet.MSBuildSdkResolver;

namespace Microsoft.DotNet.Workloads.Workload.Install
{
internal struct ManifestVersion : IEquatable<ManifestVersion>, IComparable<ManifestVersion>
internal class ManifestVersion : IEquatable<ManifestVersion>, IComparable<ManifestVersion>
sfoslund marked this conversation as resolved.
Show resolved Hide resolved
{
private string _version;
private FXVersion _version;

public ManifestVersion(string version)
{
_version = version ?? throw new ArgumentNullException(nameof(version));
if (!FXVersion.TryParse(version, out _version))
{
throw new ArgumentNullException(nameof(version));
}
}

public bool Equals(ManifestVersion other)
{
return ToString() == other.ToString();
return ToString().Equals(other.ToString());
}

public int CompareTo(ManifestVersion other)
{
return string.Compare(ToString(), other.ToString(), StringComparison.Ordinal);
return FXVersion.Compare(_version, other._version);
}

public override bool Equals(object obj)
Expand All @@ -31,12 +35,12 @@ public override bool Equals(object obj)

public override int GetHashCode()
{
return ToString().GetHashCode();
return _version.GetHashCode();
}

public override string ToString()
{
return _version;
return _version.ToString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
using Microsoft.DotNet.ToolPackage;
using Microsoft.Extensions.EnvironmentAbstractions;
using Microsoft.NET.Sdk.WorkloadManifestReader;
using NuGet.Common;
using NuGet.Versioning;
using static Microsoft.NET.Sdk.WorkloadManifestReader.WorkloadResolver;
using EnvironmentProvider = Microsoft.DotNet.NativeWrapper.EnvironmentProvider;
using Microsoft.DotNet.Workloads.Workload.Install.InstallRecord;
using NuGet.Common;

namespace Microsoft.DotNet.Workloads.Workload.Install
{
Expand All @@ -26,7 +26,7 @@ internal class NetSdkManagedInstaller : IWorkloadPackInstaller
private readonly string _installedPacksDir = "InstalledPacks";
protected readonly string _dotnetDir;
protected readonly DirectoryPath _tempPackagesDir;
private readonly INuGetPackageDownloader _nugetPackageInstaller;
private readonly INuGetPackageDownloader _nugetPackageDownloader;
private readonly IWorkloadResolver _workloadResolver;
private readonly SdkFeatureBand _sdkFeatureBand;
private readonly NetSdkManagedInstallationRecordRepository _installationRecordRepository;
Expand All @@ -41,7 +41,7 @@ public NetSdkManagedInstaller(
{
_dotnetDir = dotnetDir ?? Path.GetDirectoryName(Environment.ProcessPath);
_tempPackagesDir = new DirectoryPath(Path.Combine(_dotnetDir, "metadata", "temp"));
_nugetPackageInstaller = nugetPackageDownloader ??
_nugetPackageDownloader = nugetPackageDownloader ??
new NuGetPackageDownloader(_tempPackagesDir, verbosity.VerbosityIsDetailedOrDiagnostic() ? new NuGetConsoleLogger() : new NullLogger());
_workloadMetadataDir = Path.Combine(_dotnetDir, "metadata", "workloads");
_reporter = reporter;
Expand Down Expand Up @@ -87,7 +87,7 @@ public void InstallWorkloadPack(PackInfo packInfo, SdkFeatureBand sdkFeatureBand
{
if (!PackIsInstalled(packInfo))
{
var packagePath = _nugetPackageInstaller.DownloadPackageAsync(new PackageId(packInfo.ResolvedPackageId), new NuGetVersion(packInfo.Version)).Result;
var packagePath = _nugetPackageDownloader.DownloadPackageAsync(new PackageId(packInfo.ResolvedPackageId), new NuGetVersion(packInfo.Version)).Result;
tempFilesToDelete.Add(packagePath);

if (!Directory.Exists(Path.GetDirectoryName(packInfo.Path)))
Expand All @@ -104,7 +104,7 @@ public void InstallWorkloadPack(PackInfo packInfo, SdkFeatureBand sdkFeatureBand
var tempExtractionDir = Path.Combine(_tempPackagesDir.Value, $"{packInfo.Id}-{packInfo.Version}-extracted");
tempDirsToDelete.Add(tempExtractionDir);
Directory.CreateDirectory(tempExtractionDir);
var packFiles = _nugetPackageInstaller.ExtractPackageAsync(packagePath, tempExtractionDir).Result;
var packFiles = _nugetPackageDownloader.ExtractPackageAsync(packagePath, tempExtractionDir).Result;

FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(tempExtractionDir, packInfo.Path));
}
Expand Down Expand Up @@ -158,7 +158,77 @@ public void RollBackWorkloadPackInstall(PackInfo packInfo, SdkFeatureBand sdkFea
}
}

public void InstallWorkloadManifest(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand sdkFeatureBand) => throw new NotImplementedException();
public void InstallWorkloadManifest(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand sdkFeatureBand)
{
string packagePath = null;
string tempExtractionDir = null;
string tempBackupDir = null;
var manifestPath = Path.Combine(_dotnetDir, "sdk-manifests", sdkFeatureBand.ToString(), manifestId.ToString());

_reporter.WriteLine(string.Format(LocalizableStrings.InstallingWorkloadManifest, manifestId, manifestVersion));

try
{
TransactionalAction.Run(
action: () =>
{
packagePath = _nugetPackageDownloader.DownloadPackageAsync(WorkloadManifestUpdater.GetManifestPackageId(sdkFeatureBand, manifestId), new NuGetVersion(manifestVersion.ToString())).Result;
sfoslund marked this conversation as resolved.
Show resolved Hide resolved
tempExtractionDir = Path.Combine(_tempPackagesDir.Value, $"{manifestId}-{manifestVersion}-extracted");
Directory.CreateDirectory(tempExtractionDir);
var manifestFiles = _nugetPackageDownloader.ExtractPackageAsync(packagePath, tempExtractionDir).Result;

if (Directory.Exists(manifestPath) && Directory.GetFileSystemEntries(manifestPath).Any())
{
// Backup existing manifest data for roll back purposes
tempBackupDir = Path.Combine(_tempPackagesDir.Value, $"{manifestId}-{manifestVersion}-backup");
if (Directory.Exists(tempBackupDir))
{
Directory.Delete(tempBackupDir, true);
}
FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(manifestPath, tempBackupDir));
}
Directory.CreateDirectory(Path.GetDirectoryName(manifestPath));
FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(Path.Combine(tempExtractionDir, "data"), manifestPath));
},
rollback: () => {
if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir))
{
FileAccessRetrier.RetryOnMoveAccessFailure(() => Directory.Move(tempBackupDir, manifestPath));
}
});

// Delete leftover dirs and files
sfoslund marked this conversation as resolved.
Show resolved Hide resolved
if (!string.IsNullOrEmpty(packagePath) && File.Exists(packagePath))
{
File.Delete(packagePath);
}

var versionDir = Path.GetDirectoryName(packagePath);
if (Directory.Exists(versionDir) && !Directory.GetFileSystemEntries(versionDir).Any())
{
Directory.Delete(versionDir);
var idDir = Path.GetDirectoryName(versionDir);
if (Directory.Exists(idDir) && !Directory.GetFileSystemEntries(idDir).Any())
{
Directory.Delete(idDir);
}
}

if (!string.IsNullOrEmpty(tempExtractionDir) && Directory.Exists(tempExtractionDir))
sfoslund marked this conversation as resolved.
Show resolved Hide resolved
{
Directory.Delete(tempExtractionDir, true);
}

if (!string.IsNullOrEmpty(tempBackupDir) && Directory.Exists(tempBackupDir))
{
Directory.Delete(tempBackupDir, true);
}
}
catch (Exception e)
{
throw new Exception(string.Format(LocalizableStrings.FailedToInstallWorkloadManifest, manifestId, manifestVersion, e.Message));
}
}

public void DownloadToOfflineCache(IEnumerable<string> manifests) => throw new NotImplementedException();

Expand Down Expand Up @@ -208,7 +278,7 @@ private IEnumerable<string> GetExpectedPackInstallRecords(SdkFeatureBand sdkFeat
{
var installedWorkloads = _installationRecordRepository.GetInstalledWorkloads(sdkFeatureBand);
return installedWorkloads
.SelectMany(workload => _workloadResolver.GetPacksInWorkload(workload))
.SelectMany(workload => _workloadResolver.GetPacksInWorkload(workload.ToString()))
.Select(pack => _workloadResolver.TryGetPackInfo(pack))
.Select(packInfo => GetPackInstallRecordPath(packInfo, sdkFeatureBand));
}
Expand Down
Loading