public async Task DotnetCliTool_BasicToolRestore() { // Arrange using (var pathContext = new SimpleTestPathContext()) { var logger = new TestLogger(); var dgFile = new DependencyGraphSpec(); var spec = ToolRestoreUtility.GetSpec( Path.Combine(pathContext.SolutionRoot, "fake.csproj"), "a", VersionRange.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0")); dgFile.AddProject(spec); dgFile.AddRestore(spec.Name); var pathResolver = new ToolPathResolver(pathContext.UserPackagesFolder); var path = pathResolver.GetLockFilePath( "a", NuGetVersion.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0")); await SimpleTestPackageUtility.CreateFolderFeedV3(pathContext.PackageSource, new PackageIdentity("a", NuGetVersion.Parse("1.0.0"))); // Act var result = await CommandsTestUtility.RunSingleRestore(dgFile, pathContext, logger); // Assert Assert.True(result.Success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); Assert.True(File.Exists(path)); } }
private string GetAssetsFilePath(LockFile lockFile) { var projectLockFilePath = _request.LockFilePath; if (string.IsNullOrEmpty(projectLockFilePath)) { if (_request.ProjectStyle == ProjectStyle.PackageReference || _request.ProjectStyle == ProjectStyle.Standalone) { projectLockFilePath = Path.Combine(_request.RestoreOutputPath, LockFileFormat.AssetsFileName); } else if (_request.ProjectStyle == ProjectStyle.DotnetCliTool) { var toolName = ToolRestoreUtility.GetToolIdOrNullFromSpec(_request.Project); var lockFileLibrary = ToolRestoreUtility.GetToolTargetLibrary(lockFile, toolName); if (lockFileLibrary != null) { var version = lockFileLibrary.Version; var toolPathResolver = new ToolPathResolver(_request.PackagesDirectory); projectLockFilePath = toolPathResolver.GetLockFilePath( toolName, version, lockFile.Targets.First().TargetFramework); } } else { projectLockFilePath = Path.Combine(_request.Project.BaseDirectory, LockFileFormat.LockFileName); } } return(Path.GetFullPath(projectLockFilePath)); }
public async Task DotnetCliTool_BasicToolRestore_DifferentVersionRanges() { // Arrange using (var pathContext = new SimpleTestPathContext()) { var logger = new TestLogger(); var dgFile = new DependencyGraphSpec(); var versions = new List <VersionRange>(); var limit = 100; for (int i = 0; i < limit; i++) { var version = VersionRange.Parse($"{i + 1}.0.0"); versions.Add(version); var spec = ToolRestoreUtility.GetSpec( Path.Combine(pathContext.SolutionRoot, $"fake{i}.csproj"), "a", version, NuGetFramework.Parse("netcoreapp1.0")); dgFile.AddProject(spec); dgFile.AddRestore(spec.Name); } var pathResolver = new ToolPathResolver(pathContext.UserPackagesFolder); foreach (var version in versions) { await SimpleTestPackageUtility.CreateFolderFeedV3(pathContext.PackageSource, new PackageIdentity("a", version.MinVersion)); } // Act var results = await CommandsTestUtility.RunRestore(dgFile, pathContext, logger); // Assert Assert.Equal(limit, results.Count); foreach (var result in results) { Assert.True(result.Success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); } foreach (var version in versions) { var path = pathResolver.GetLockFilePath( "a", version.MinVersion, NuGetFramework.Parse("netcoreapp1.0")); Assert.True(File.Exists(path)); } } }
public async Task DotnetCliTool_BasicToolRestore_WithDuplicates() { // Arrange using (var pathContext = new SimpleTestPathContext()) { var logger = new TestLogger(); var dgFile = new DependencyGraphSpec(); for (int i = 0; i < 10; i++) { var spec = ToolRestoreUtility.GetSpec( Path.Combine(pathContext.SolutionRoot, "fake.csproj"), "a", VersionRange.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0"), pathContext.UserPackagesFolder, new List <string>() { pathContext.FallbackFolder }, new List <PackageSource>() { new PackageSource(pathContext.PackageSource) }, projectWideWarningProperties: null); dgFile.AddProject(spec); dgFile.AddRestore(spec.Name); } var pathResolver = new ToolPathResolver(pathContext.UserPackagesFolder); var path = pathResolver.GetLockFilePath( "a", NuGetVersion.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0")); await SimpleTestPackageUtility.CreateFolderFeedV3Async(pathContext.PackageSource, new PackageIdentity("a", NuGetVersion.Parse("1.0.0"))); // Act var results = await CommandsTestUtility.RunRestore(dgFile, pathContext, logger); // Assert // This should have been de-duplicated Assert.Equal(1, results.Count); var result = results.Single(); Assert.True(result.Success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); Assert.True(File.Exists(path)); } }
/// <summary> /// This method will resolve the cache/lock file paths for the tool if available in the cache /// This method will set the CacheFilePath and the LockFilePath in the RestoreMetadat if a matching tool is available /// </summary> public static void UpdateRequestBestMatchingToolPathsIfAvailable(RestoreRequest request) { if (request.ProjectStyle == ProjectStyle.DotnetCliTool) { // Resolve the lock file path if it exists var toolPathResolver = new ToolPathResolver(request.PackagesDirectory); var toolDirectory = toolPathResolver.GetBestToolDirectoryPath( ToolRestoreUtility.GetToolIdOrNullFromSpec(request.Project), request.Project.TargetFrameworks.First().Dependencies.First().LibraryRange.VersionRange, request.Project.TargetFrameworks.SingleOrDefault().FrameworkName); if (toolDirectory != null) // Only set the paths if a good enough match was found. { request.Project.RestoreMetadata.CacheFilePath = NoOpRestoreUtilities.GetToolCacheFilePath(toolDirectory, ToolRestoreUtility.GetToolIdOrNullFromSpec(request.Project)); request.LockFilePath = toolPathResolver.GetLockFilePath(toolDirectory); } } }
internal static string GetToolCacheFilePath(RestoreRequest request, LockFile lockFile) { if (request.ProjectStyle != ProjectStyle.DotnetCliTool) { var toolName = ToolRestoreUtility.GetToolIdOrNullFromSpec(request.Project); var lockFileLibrary = ToolRestoreUtility.GetToolTargetLibrary(lockFile, toolName); if (lockFileLibrary != null) { var version = lockFileLibrary.Version; var toolPathResolver = new ToolPathResolver(request.PackagesDirectory); var projFileName = Path.GetFileName(request.Project.RestoreMetadata.ProjectPath); return(PathUtility.GetDirectoryName(toolPathResolver.GetLockFilePath( toolName, version, lockFile.Targets.First().TargetFramework)) + $"{projFileName}.nuget.cache"); } } return(null); }
public void ToolPathResolver_BuildsOriginalCaseLockFilePath() { // Arrange var target = new ToolPathResolver("packages", isLowercase: false); var expected = Path.Combine( "packages", ".tools", "PackageA", "3.1.4-BETA", "netstandard1.3", "project.assets.json"); // Act var actual = target.GetLockFilePath( "PackageA", NuGetVersion.Parse("3.1.4-BETA"), FrameworkConstants.CommonFrameworks.NetStandard13); // Assert Assert.Equal(expected, actual); }
private async Task <IEnumerable <ToolRestoreResult> > ExecuteToolRestoresAsync( NuGetv3LocalRepository localRepository, CancellationToken token) { var toolPathResolver = new ToolPathResolver(_request.PackagesDirectory); var results = new List <ToolRestoreResult>(); foreach (var tool in _request.Project.Tools) { _logger.LogMinimal(string.Format( CultureInfo.CurrentCulture, Strings.Log_RestoringToolPackages, tool.LibraryRange.Name, _request.Project.FilePath)); // Build the fallback framework (which uses the "imports"). var framework = LockFile.ToolFramework; if (tool.Imports.Any()) { framework = new FallbackFramework(framework, tool.Imports); } // Build a package spec in memory to execute the tool restore as if it were // its own project. For now, we always restore for a null runtime and a single // constant framework. var toolPackageSpec = new PackageSpec(new JObject()) { Name = Guid.NewGuid().ToString(), // make sure this package never collides with a dependency Dependencies = new List <LibraryDependency>(), Tools = new List <ToolDependency>(), TargetFrameworks = { new TargetFrameworkInformation { FrameworkName = framework, Dependencies = new List <LibraryDependency> { new LibraryDependency { LibraryRange = tool.LibraryRange } } } } }; // Try to find the existing lock file. Since the existing lock file is pathed under // a folder that includes the resolved tool's version, this is a bit of a chicken // and egg problem. That is, we need to run the restore operation in order to resolve // a tool version, but we need the tool version to find the existing project.lock.json // file which is required before executing the restore! Fortunately, this is solved by // looking at the tool's consuming project's lock file to see if the tool has been // restored before. LockFile existingToolLockFile = null; if (_request.ExistingLockFile != null) { var existingTarget = _request .ExistingLockFile .Tools .Where(t => t.RuntimeIdentifier == null) .Where(t => t.TargetFramework.Equals(LockFile.ToolFramework)) .FirstOrDefault(); var existingLibrary = existingTarget?.Libraries .Where(l => StringComparer.OrdinalIgnoreCase.Equals(l.Name, tool.LibraryRange.Name)) .Where(l => tool.LibraryRange.VersionRange.Satisfies(l.Version)) .FirstOrDefault(); if (existingLibrary != null) { var existingLockFilePath = toolPathResolver.GetLockFilePath( existingLibrary.Name, existingLibrary.Version, existingTarget.TargetFramework); existingToolLockFile = LockFileUtilities.GetLockFile(existingLockFilePath, _logger); } } // Execute the restore. var toolSuccess = true; // success for this individual tool restore var runtimeIds = new HashSet <string>(); var projectFrameworkRuntimePairs = CreateFrameworkRuntimePairs(toolPackageSpec, runtimeIds); var allInstalledPackages = new HashSet <LibraryIdentity>(); var contextForTool = CreateRemoteWalkContext(_request); var walker = new RemoteDependencyWalker(contextForTool); var projectRestoreRequest = new ProjectRestoreRequest( _request, toolPackageSpec, existingToolLockFile, new Dictionary <NuGetFramework, RuntimeGraph>(), _runtimeGraphCacheByPackage); var projectRestoreCommand = new ProjectRestoreCommand(_logger, projectRestoreRequest); var result = await projectRestoreCommand.TryRestore( tool.LibraryRange, projectFrameworkRuntimePairs, allInstalledPackages, localRepository, walker, contextForTool, writeToLockFile : true, token : token); var graphs = result.Item2; if (!result.Item1) { toolSuccess = false; _success = false; } // Create the lock file (in memory). var toolLockFile = BuildLockFile( existingToolLockFile, toolPackageSpec, graphs, localRepository, contextForTool, Enumerable.Empty <ToolRestoreResult>(), false); // Build the path based off of the resolved tool. For now, we assume there is only // ever one target. var target = toolLockFile.Targets.Single(); var fileTargetLibrary = target .Libraries .FirstOrDefault(l => StringComparer.OrdinalIgnoreCase.Equals(tool.LibraryRange.Name, l.Name)); string toolLockFilePath = null; if (fileTargetLibrary != null) { toolLockFilePath = toolPathResolver.GetLockFilePath( fileTargetLibrary.Name, fileTargetLibrary.Version, target.TargetFramework); } // Validate the results. if (!ValidateRestoreGraphs(graphs, _logger)) { toolSuccess = false; _success = false; } var checkResults = VerifyCompatibility( toolPackageSpec, new Dictionary <RestoreTargetGraph, Dictionary <string, LibraryIncludeFlags> >(), localRepository, toolLockFile, graphs, _logger); if (checkResults.Any(r => !r.Success)) { toolSuccess = false; _success = false; } results.Add(new ToolRestoreResult( tool.LibraryRange.Name, toolSuccess, target, fileTargetLibrary, toolLockFilePath, toolLockFile, existingToolLockFile)); } return(results); }
public async Task DotnetCliTool_VerifyProjectsAreNotAllowed() { // Arrange using (var pathContext = new SimpleTestPathContext()) { var logger = new TestLogger(); var dgFile = new DependencyGraphSpec(); var spec = ToolRestoreUtility.GetSpec( Path.Combine(pathContext.SolutionRoot, "tool", "fake.csproj"), "a", VersionRange.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0"), pathContext.UserPackagesFolder, new List <string>() { pathContext.FallbackFolder }, new List <PackageSource>() { new PackageSource(pathContext.PackageSource) }, projectWideWarningProperties: null); dgFile.AddProject(spec); dgFile.AddRestore(spec.Name); var pathResolver = new ToolPathResolver(pathContext.UserPackagesFolder); var path = pathResolver.GetLockFilePath( "a", NuGetVersion.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0")); var packageA = new SimpleTestPackageContext() { Id = "a", Version = "1.0.0" }; var packageB = new SimpleTestPackageContext() { Id = "b", Version = "1.0.0" }; packageA.Dependencies.Add(packageB); await SimpleTestPackageUtility.CreateFolderFeedV3Async( pathContext.PackageSource, PackageSaveMode.Defaultv3, packageA, packageB); var projectYRoot = Path.Combine(pathContext.SolutionRoot, "b"); Directory.CreateDirectory(projectYRoot); var projectYJson = Path.Combine(projectYRoot, "project.json"); var projectJsonContent = JObject.Parse(@"{ 'dependencies': { }, 'frameworks': { 'netstandard1.0': { } } }"); File.WriteAllText(projectYJson, projectJsonContent.ToString()); // Act var result = await CommandsTestUtility.RunSingleRestore(dgFile, pathContext, logger); // Assert Assert.True(result.Success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); Assert.True(File.Exists(path)); var lockFormat = new LockFileFormat(); var lockFile = lockFormat.Read(path); // Verify only packages Assert.Empty(lockFile.Libraries.Where(e => e.Type != "package")); } }
public async Task DotnetCliTool_ToolRestoreNoOpsRegardlessOfProject() { // Arrange using (var pathContext = new SimpleTestPathContext()) { var logger1 = new TestLogger(); var logger2 = new TestLogger(); var spec1 = ToolRestoreUtility.GetSpec( Path.Combine(pathContext.SolutionRoot, "fake1.csproj"), "a", VersionRange.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0"), pathContext.UserPackagesFolder, new List <string>() { pathContext.FallbackFolder }, new List <PackageSource>() { new PackageSource(pathContext.PackageSource) }, projectWideWarningProperties: null); var spec2 = ToolRestoreUtility.GetSpec( Path.Combine(pathContext.SolutionRoot, "fake2.csproj"), "a", VersionRange.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0"), pathContext.UserPackagesFolder, new List <string>() { pathContext.FallbackFolder }, new List <PackageSource>() { new PackageSource(pathContext.PackageSource) }, projectWideWarningProperties: null); var dgFile1 = new DependencyGraphSpec(); dgFile1.AddProject(spec1); dgFile1.AddRestore(spec1.Name); var dgFile2 = new DependencyGraphSpec(); dgFile2.AddProject(spec2); dgFile2.AddRestore(spec2.Name); var pathResolver = new ToolPathResolver(pathContext.UserPackagesFolder); var path = pathResolver.GetLockFilePath( "a", NuGetVersion.Parse("1.0.0"), NuGetFramework.Parse("netcoreapp1.0")); await SimpleTestPackageUtility.CreateFolderFeedV3Async(pathContext.PackageSource, new PackageIdentity("a", NuGetVersion.Parse("1.0.0"))); // Act var results1 = await CommandsTestUtility.RunRestore(dgFile1, pathContext, logger1); // Assert Assert.Equal(1, results1.Count); var result1 = results1.Single(); Assert.True(result1.Success, "Failed: " + string.Join(Environment.NewLine, logger1.Messages)); Assert.False(result1.NoOpRestore, "Should not no-op: " + string.Join(Environment.NewLine, logger1.Messages)); Assert.True(File.Exists(path)); // Act var results2 = await CommandsTestUtility.RunRestore(dgFile2, pathContext, logger2); // Assert Assert.Equal(1, results2.Count); var result2 = results2.Single(); Assert.True(result2.Success, "Failed: " + string.Join(Environment.NewLine, logger2.Messages)); Assert.True(result2.NoOpRestore, "Should no-op: " + string.Join(Environment.NewLine, logger2.Messages)); Assert.True(File.Exists(path)); } }