Skip to content

Commit

Permalink
Support reading package folder locations out of the lock file
Browse files Browse the repository at this point in the history
The task previously was constructing the path to the user's packages
location itself, which had various issues. It meant that if the restore
was done with a different path, we don't know that. It also meant we
didn't handle the paths specified in nuget.config. Now, if the paths
are present in the lock file, we'll use that. Otherwise, we'll construct
our old path as before. Any explicitly given path to the task is
still used no matter what.
  • Loading branch information
jasonmalinowski committed Jun 14, 2016
1 parent 4a5f280 commit d37c917
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 33 deletions.
28 changes: 28 additions & 0 deletions src/Microsoft.NuGet.Build.Tasks.Tests/Json/Json.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Microsoft.NuGet.Build.Tasks.Tests/Json/Json.resx
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,7 @@
<data name="nativeWinMD" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>nativeWinMD.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="LockFileWithWithSpecifiedPackageFolders" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>lockfilewithwithspecifiedpackagefolders.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"locked": false,
"version": 2,
"targets": {
".NETFramework,Version=v4.5": {
"Newtonsoft.Json/8.0.3": {
"type": "package",
"compile": {
"lib/net45/Newtonsoft.Json.dll": {}
},
"runtime": {
"lib/net45/Newtonsoft.Json.dll": {}
}
}
}
},
"libraries": {
"Newtonsoft.Json/8.0.3": {
"sha512": "KGsYQdS2zLH+H8x2cZaSI7e+YZ4SFIbyy1YJQYl6GYBWjf5o4H1A68nxyq+WTyVSOJQ4GqS/DiPE+UseUizgMg==",
"type": "package",
"path": "newtonsoft.json/8.0.3",
"files": [
"lib/net20/Newtonsoft.Json.dll",
"lib/net20/Newtonsoft.Json.xml",
"lib/net35/Newtonsoft.Json.dll",
"lib/net35/Newtonsoft.Json.xml",
"lib/net40/Newtonsoft.Json.dll",
"lib/net40/Newtonsoft.Json.xml",
"lib/net45/Newtonsoft.Json.dll",
"lib/net45/Newtonsoft.Json.xml",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.xml",
"lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll",
"lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.xml",
"newtonsoft.json.8.0.3.nupkg.sha512",
"newtonsoft.json.nuspec",
"tools/install.ps1"
]
}
},
"projectFileDependencyGroups": {
"": [
"Newtonsoft.Json"
],
".NETFramework,Version=v4.5": []
},
"tools": {},
"projectFileToolGroups": {},
"packageFolders": {
"C:\\PackageFolder\\": {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<DependentUpon>Json.resx</DependentUpon>
</Compile>
<Compile Include="NuGetTestHelpers.cs" />
<Compile Include="PackageFolderTests.cs" />
<Compile Include="PreprocessorTests.cs" />
<Compile Include="ProjectReferences\ProjectReferenceTests.cs" />
<Compile Include="ProjectReferences\Resources.Designer.cs">
Expand All @@ -78,6 +79,7 @@
<None Include="Json\FluentAssertions.lock.json" />
<None Include="Json\FluentAssertionsAndWin10.lock.json" />
<None Include="Json\nativeWinMD.json" />
<None Include="Json\LockFileWithWithSpecifiedPackageFolders.json" />
<None Include="Json\Win10.Edm.json" />
<None Include="Json\Win10.json" />
<None Include="Json\Win10.xunit.json" />
Expand Down
26 changes: 18 additions & 8 deletions src/Microsoft.NuGet.Build.Tasks.Tests/NuGetTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ public static ResolvePackagesResult ResolvePackagesWithJsonFileContents(
TryGetRuntimeVersion tryGetRuntimeVersion = null,
bool includeFrameworkReferences = true,
string projectJsonFileContents = null,
IEnumerable<ITaskItem> projectReferencesCreatingPackages = null)
IEnumerable<ITaskItem> projectReferencesCreatingPackages = null,
bool createTemporaryFolderForPackages = true)
{
var rootDirectory = new TempRoot();
using (rootDirectory)
{
var projectDirectory = rootDirectory.CreateDirectory();
var packagesDirectory = rootDirectory.CreateDirectory();

var projectLockJsonFile = projectDirectory.CreateFile("project.lock.json");
projectLockJsonFile.WriteAllText(projectLockJsonFileContents);
Expand All @@ -43,21 +43,31 @@ public static ResolvePackagesResult ResolvePackagesWithJsonFileContents(
projectJsonFile.WriteAllText(projectJsonFileContents);
}

var filesInPackages = new HashSet<string>(
GetFakeFileNamesFromPackages(projectLockJsonFileContents, packagesDirectory.Path),
StringComparer.OrdinalIgnoreCase);
var filesInPackages = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
DisposableDirectory packagesDirectory = null;

if (createTemporaryFolderForPackages)
{
packagesDirectory = rootDirectory.CreateDirectory();

foreach (var fileInPackage in GetFakeFileNamesFromPackages(projectLockJsonFileContents, packagesDirectory.Path))
{
filesInPackages.Add(fileInPackage);
}
}

// Don't require the packages be restored on the machine
DirectoryExists directoryExists = path => path.StartsWith(packagesDirectory.Path) || Directory.Exists(path);
ResolveNuGetPackageAssets task = null;
DirectoryExists directoryExists = path => task.GetPackageFolders().Any(l => path.StartsWith(l)) || Directory.Exists(path);
FileExists fileExists = path => filesInPackages.Contains(path) || File.Exists(path);

ResolveNuGetPackageAssets task = new ResolveNuGetPackageAssets(directoryExists, fileExists, tryGetRuntimeVersion);
task = new ResolveNuGetPackageAssets(directoryExists, fileExists, tryGetRuntimeVersion);
var sw = new StringWriter();
task.BuildEngine = new MockBuildEngine(sw);

task.AllowFallbackOnTargetSelection = allowFallbackOnTargetSelection;
task.IncludeFrameworkReferences = includeFrameworkReferences;
task.NuGetPackagesDirectory = packagesDirectory.Path;
task.NuGetPackagesDirectory = packagesDirectory?.Path;
task.RuntimeIdentifier = runtimeIdentifier;
task.ProjectReferencesCreatingPackages = (projectReferencesCreatingPackages ?? Enumerable.Empty<ITaskItem>()).ToArray();
task.ProjectLockFile = projectLockJsonFile.Path;
Expand Down
24 changes: 24 additions & 0 deletions src/Microsoft.NuGet.Build.Tasks.Tests/PackageFolderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace Microsoft.NuGet.Build.Tasks.Tests
{
public class PackageFolderTests
{
[Fact]
public void ResolveWithLockFileWithPackageFolders()
{
var result = NuGetTestHelpers.ResolvePackagesWithJsonFileContents(
Json.Json.LockFileWithWithSpecifiedPackageFolders,
".NETFramework,Version=v4.5",
runtimeIdentifier: null,
createTemporaryFolderForPackages: false);

Assert.Equal(@"C:\PackageFolder\Newtonsoft.Json\8.0.3\lib\net45\Newtonsoft.Json.dll", result.References.Single().ItemSpec);
}
}
}
81 changes: 56 additions & 25 deletions src/Microsoft.NuGet.Build.Tasks/ResolveNuGetPackageAssets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public sealed class ResolveNuGetPackageAssets : Task
private readonly List<ITaskItem> _contentItems = new List<ITaskItem>();
private readonly List<ITaskItem> _fileWrites = new List<ITaskItem>();

private readonly List<string> _packageFolders = new List<string>();

private readonly Dictionary<string, string> _projectReferencesToOutputBasePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

#region UnitTestSupport
Expand Down Expand Up @@ -72,6 +74,13 @@ internal ResolveNuGetPackageAssets(DirectoryExists directoryExists, FileExists f

_reportExceptionsToMSBuildLogger = false;
}

// For unit testing.
internal IEnumerable<string> GetPackageFolders()
{
return _packageFolders;
}

#endregion

/// <summary>
Expand Down Expand Up @@ -233,6 +242,8 @@ private void ExecuteCore()
lockFile = JObject.Load(new JsonTextReader(streamReader));
}

PopulatePackageFolders(lockFile);

PopulateProjectReferenceMaps();
GetReferences(lockFile);
GetCopyLocalItems(lockFile);
Expand All @@ -241,6 +252,41 @@ private void ExecuteCore()
ProduceContentAssets(lockFile);
}

private void PopulatePackageFolders(JObject lockFile)
{
// If we explicitly were given a path, let's use that
if (!string.IsNullOrEmpty(NuGetPackagesDirectory))
{
_packageFolders.Add(NuGetPackagesDirectory);
}

// Newer versions of NuGet can now specify the final list of locations in the lock file
var packageFolders = lockFile["packageFolders"] as JObject;

if (packageFolders != null)
{
foreach (var packageFolder in packageFolders.Properties())
{
_packageFolders.Add(packageFolder.Name);
}
}

// If we didn't have any folders, let's fall back to the environment variable or user profile
if (_packageFolders.Count == 0)
{
string packagesFolder = Environment.GetEnvironmentVariable("NUGET_PACKAGES");

if (!string.IsNullOrEmpty(packagesFolder))
{
_packageFolders.Add(packagesFolder);
}
else
{
_packageFolders.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages"));
}
}
}

private void PopulateProjectReferenceMaps()
{
foreach (var projectReference in ProjectReferencesCreatingPackages ?? new ITaskItem[] { })
Expand Down Expand Up @@ -579,7 +625,7 @@ private static string GetNuGetLanguageName(string projectLanguage)
private void ProduceContentAsset(NuGetPackageObject package, JProperty sharedAsset, IReadOnlyDictionary<string, string> preprocessorValues, string preprocessedOutputDirectory)
{
string pathToFinalAsset = package.GetFullPathToFile(sharedAsset.Name);

if (sharedAsset.Value["ppOutputPath"] != null)
{
if (preprocessedOutputDirectory == null)
Expand Down Expand Up @@ -775,7 +821,7 @@ private IEnumerable<ITaskItem> CreateItems(NuGetPackageObject package, string ke
{
targetPath = Path.Combine(culture, Path.GetFileName(file.Name));
}

var item = CreateItem(package, package.GetFullPathToFile(file.Name), targetPath);

item.SetMetadata("Private", "false");
Expand Down Expand Up @@ -844,32 +890,17 @@ private void GetReferencedPackages(JObject lockFile)

private string GetNuGetPackagePath(string packageId, string packageVersion)
{
string packagesFolder = GetNuGetPackagesPath();
string packagePath = Path.Combine(packagesFolder, packageId, packageVersion);

if (!_directoryExists(packagePath))
foreach (var packagesFolder in _packageFolders)
{
throw new ExceptionFromResource(nameof(Strings.PackageFolderNotFound), packageId, packageVersion, packagesFolder);
}

return packagePath;
}
string packagePath = Path.Combine(packagesFolder, packageId, packageVersion);

private string GetNuGetPackagesPath()
{
if (!string.IsNullOrEmpty(NuGetPackagesDirectory))
{
return NuGetPackagesDirectory;
}

string packagesFolder = Environment.GetEnvironmentVariable("NUGET_PACKAGES");

if (!string.IsNullOrEmpty(packagesFolder))
{
return packagesFolder;
if (_directoryExists(packagePath))
{
return packagePath;
}
}

return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
throw new ExceptionFromResource(nameof(Strings.PackageFolderNotFound), packageId, packageVersion, string.Join(", ", _packageFolders));
}

private IEnumerable<NuGetPackageObject> GetPackagesFromTarget(JObject lockFile, JObject target)
Expand Down Expand Up @@ -915,7 +946,7 @@ private IEnumerable<NuGetPackageObject> GetPackagesFromTarget(JObject lockFile,
};
}
else
{
{
fullPackagePathGenerator = () => GetNuGetPackagePath(id, version);
}

Expand Down

0 comments on commit d37c917

Please sign in to comment.