Skip to content

Commit

Permalink
Repeatable build using Project lock file implementation
Browse files Browse the repository at this point in the history
generating/ updating project lock file

consuming project lock file during restore in VS

Validation of package's sha512 and added error messages as appropriate

Test infra for legacy PackageReference func tests

Base workflow is completed
  • Loading branch information
jainaashish committed Aug 8, 2018
1 parent 16fdc22 commit 0b0e8bd
Show file tree
Hide file tree
Showing 49 changed files with 2,963 additions and 262 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,10 @@ private async Task<PackageSpec> GetPackageSpecAsync(ISettings settings)
ProjectWideWarningProperties = WarningProperties.GetWarningProperties(
treatWarningsAsErrors: _vsProjectAdapter.TreatWarningsAsErrors,
noWarn: _vsProjectAdapter.NoWarn,
warningsAsErrors: _vsProjectAdapter.WarningsAsErrors)
warningsAsErrors: _vsProjectAdapter.WarningsAsErrors),
RestorePackagesWithLockFile = await _vsProjectAdapter.GetRestorePackagesWithLockFileAsync(),
NuGetLockFilePath = await _vsProjectAdapter.GetNuGetLockFilePathAsync(),
FreezeLockFileOnRestore = await _vsProjectAdapter.IsLockFileFreezeOnRestoreAsync()
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,31 @@ public async Task<NuGetFramework> GetTargetFrameworkAsync()
return NuGetFramework.UnsupportedFramework;
}

public async Task<string> GetRestorePackagesWithLockFileAsync()
{
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();

var value = await BuildProperties.GetPropertyValueAsync(ProjectBuildProperties.RestorePackagesWithLockFile);

return value;
}

public async Task<string> GetNuGetLockFilePathAsync()
{
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();

return await BuildProperties.GetPropertyValueAsync(ProjectBuildProperties.NuGetLockFilePath);
}

public async Task<bool> IsLockFileFreezeOnRestoreAsync()
{
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();

var value = await BuildProperties.GetPropertyValueAsync(ProjectBuildProperties.FreezeLockFileOnRestore);

return MSBuildStringUtility.IsTrue(value);
}

private async Task<string> GetTargetFrameworkStringAsync()
{
await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public sealed class VsSolutionRestoreService : IVsSolutionRestoreService, IVsSol
private const string TreatWarningsAsErrors = nameof(TreatWarningsAsErrors);
private const string WarningsAsErrors = nameof(WarningsAsErrors);
private const string NoWarn = nameof(NoWarn);
private const string RestorePackagesWithLockFile = nameof(RestorePackagesWithLockFile);
private const string NuGetLockFilePath = nameof(NuGetLockFilePath);
private const string FreezeLockFileOnRestore = nameof(FreezeLockFileOnRestore);


private static readonly Version Version20 = new Version(2, 0, 0, 0);
Expand Down Expand Up @@ -286,7 +289,10 @@ private static PackageSpec ToPackageSpec(ProjectNames projectNames, IVsProjectRe
treatWarningsAsErrors: GetSingleOrDefaultPropertyValue(projectRestoreInfo.TargetFrameworks, TreatWarningsAsErrors, e => e),
warningsAsErrors: GetSingleOrDefaultNuGetLogCodes(projectRestoreInfo.TargetFrameworks, WarningsAsErrors, e => MSBuildStringUtility.GetNuGetLogCodes(e)),
noWarn: GetSingleOrDefaultNuGetLogCodes(projectRestoreInfo.TargetFrameworks, NoWarn, e => MSBuildStringUtility.GetNuGetLogCodes(e))),
CacheFilePath = NoOpRestoreUtilities.GetProjectCacheFilePath(cacheRoot: outputPath, projectPath: projectFullPath)
CacheFilePath = NoOpRestoreUtilities.GetProjectCacheFilePath(cacheRoot: outputPath, projectPath: projectFullPath),
RestorePackagesWithLockFile = GetRestorePackagesWithLockFile(projectRestoreInfo.TargetFrameworks),
NuGetLockFilePath = GetNuGetLockFilePath(projectRestoreInfo.TargetFrameworks),
FreezeLockFileOnRestore = IsLockFileFreezeOnRestore(projectRestoreInfo.TargetFrameworks)
},
RuntimeGraph = GetRuntimeGraph(projectRestoreInfo),
RestoreSettings = new ProjectRestoreSettings() { HideWarningsAndErrors = true }
Expand Down Expand Up @@ -316,6 +322,21 @@ private static string GetRestoreProjectPath(IVsTargetFrameworks tfms)
return GetSingleNonEvaluatedPropertyOrNull(tfms, RestorePackagesPath, e => e);
}

private static string GetRestorePackagesWithLockFile(IVsTargetFrameworks tfms)
{
return GetSingleNonEvaluatedPropertyOrNull(tfms, RestorePackagesWithLockFile, v => v);
}

private static string GetNuGetLockFilePath(IVsTargetFrameworks tfms)
{
return GetSingleNonEvaluatedPropertyOrNull(tfms, NuGetLockFilePath, v => v);
}

private static bool IsLockFileFreezeOnRestore(IVsTargetFrameworks tfms)
{
return GetSingleNonEvaluatedPropertyOrNull(tfms, FreezeLockFileOnRestore, MSBuildStringUtility.IsTrue);
}

/// <summary>
/// The result will contain CLEAR and no sources specified in RestoreSources if the clear keyword is in it.
/// If there are additional sources specified, the value AdditionalValue will be set in the result and then all the additional sources will follow
Expand Down
18 changes: 18 additions & 0 deletions src/NuGet.Clients/NuGet.VisualStudio.Common/IVsProjectAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,23 @@ public interface IVsProjectAdapter
/// Project's target framework
/// </summary>
Task<NuGetFramework> GetTargetFrameworkAsync();

/// <summary>
/// RestorePackagesWithLockFile project property.
/// </summary>
/// <returns></returns>
Task<string> GetRestorePackagesWithLockFileAsync();

/// <summary>
/// NuGetLockFilePath project property.
/// </summary>
/// <returns></returns>
Task<string> GetNuGetLockFilePathAsync();

/// <summary>
/// FreezeLockFileOnRestore project property.
/// </summary>
/// <returns></returns>
Task<bool> IsLockFileFreezeOnRestoreAsync();
}
}
102 changes: 102 additions & 0 deletions src/NuGet.Core/NuGet.Commands/NuGetLockFileBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NuGet.Common;
using NuGet.Frameworks;
using NuGet.LibraryModel;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
using NuGet.Shared;

namespace NuGet.Commands
{
public class NuGetLockFileBuilder
{
private readonly int _lockFileVersion;
public NuGetLockFileBuilder(int lockFileVersion)
{
_lockFileVersion = lockFileVersion;
}

public NuGetLockFile CreateNuGetLockFile(LockFile assetsFile)
{
var lockFile = new NuGetLockFile()
{
Version = _lockFileVersion
};

var libraryLookup = assetsFile.Libraries.Where(e => e.Type == LibraryType.Package)
.ToDictionary(e => new PackageIdentity(e.Name, e.Version));

foreach (var target in assetsFile.Targets)
{
var nuGettarget = new NuGetLockFileTarget()
{
TargetFramework = target.TargetFramework,
RuntimeIdentifier = target.RuntimeIdentifier
};

var framework = assetsFile.PackageSpec.TargetFrameworks.FirstOrDefault(
f => EqualityUtility.EqualsWithNullCheck(f.FrameworkName, target.TargetFramework));

var lilbraries = target.Libraries;

// check if this is RID-based graph then only add those libraries which differ from original TFM.
if (!string.IsNullOrEmpty(target.RuntimeIdentifier))
{
var onlyTFM = assetsFile.Targets.First(t => EqualityUtility.EqualsWithNullCheck(t.TargetFramework, target.TargetFramework));

lilbraries = target.Libraries.Where(lib => !onlyTFM.Libraries.Any(tfmLib => tfmLib.Equals(lib))).ToList();
}

foreach (var library in lilbraries.Where(e => e.Type == LibraryType.Package))
{
var identity = new PackageIdentity(library.Name, library.Version);

var dependency = new LockFileDependency()
{
Id = library.Name,
ResolvedVersion = library.Version,
Sha512 = libraryLookup[identity].Sha512,
Dependencies = library.Dependencies
};

var framework_dep = framework.Dependencies.FirstOrDefault(
dep => PathUtility.GetStringComparerBasedOnOS().Equals(dep.Name, library.Name));

if (framework_dep != null)
{
dependency.Type = PackageInstallationType.Direct;
dependency.RequestedVersion = framework_dep.LibraryRange.VersionRange;
}
else
{
dependency.Type = PackageInstallationType.Transitive;
}

nuGettarget.Dependencies.Add(dependency);
}

foreach (var projectRef in lilbraries.Where(e => e.Type == LibraryType.Project || e.Type == LibraryType.ExternalProject))
{
var dependency = new LockFileDependency()
{
Id = projectRef.Name,
Dependencies = projectRef.Dependencies,
Type = PackageInstallationType.Project
};

nuGettarget.Dependencies.Add(dependency);
}

nuGettarget.Dependencies = nuGettarget.Dependencies.OrderBy(d => d.Type).ToList();

lockFile.Targets.Add(nuGettarget);
}

return lockFile;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ private static ExternalProjectReference GetExternalProject(PackageSpec rootProje
RestoreOutputPath = project.PackageSpec.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson ? rootPath : project.PackageSpec.RestoreMetadata.OutputPath,
DependencyGraphSpec = projectDgSpec,
MSBuildProjectExtensionsPath = projectPackageSpec.RestoreMetadata.OutputPath,
ParentId = restoreArgs.ParentId
ParentId = restoreArgs.ParentId,
IsRestore = restoreArgs.IsRestore
};

var restoreLegacyPackagesDirectory = project.PackageSpec?.RestoreMetadata?.LegacyPackagesDirectory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class NoOpRestoreResult : RestoreResult
public NoOpRestoreResult(bool success, LockFile lockFile, LockFile previousLockFile, string lockFilePath, CacheFile cacheFile, string cacheFilePath, ProjectStyle projectStyle, TimeSpan elapsedTime) :
base(success : success, restoreGraphs : null, compatibilityCheckResults : new List<CompatibilityCheckResult>() ,
msbuildFiles : null, lockFile : lockFile, previousLockFile : previousLockFile, lockFilePath: lockFilePath,
cacheFile: cacheFile, cacheFilePath: cacheFilePath, projectStyle: projectStyle, elapsedTime: elapsedTime)
cacheFile: cacheFile, cacheFilePath: cacheFilePath, nuGetLockFilePath:null, nuGetLockFile:null, projectStyle: projectStyle, elapsedTime: elapsedTime)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public class RestoreArgs

public Guid ParentId { get; set; }

public bool IsRestore { get; set; } = true;

// Cache directory -> ISettings
private ConcurrentDictionary<string, ISettings> _settingsCache
= new ConcurrentDictionary<string, ISettings>(StringComparer.Ordinal);
Expand Down
Loading

0 comments on commit 0b0e8bd

Please sign in to comment.