public async Task RestoreBuildTargetsAndProps_VerifyPropsAndTargetsGeneratedWithNoTFMConditionsAsync() { // Arrange using (var cacheContext = new SourceCacheContext()) using (var pathContext = new SimpleTestPathContext()) { var logger = new TestLogger(); var sources = new List <PackageSource> { new PackageSource(pathContext.PackageSource) }; var spec = GetProject("projectA", "net462"); spec.RestoreMetadata.CrossTargeting = false; spec.Dependencies.Add(new LibraryDependency() { LibraryRange = new LibraryRange("x", VersionRange.Parse("1.0.0"), LibraryDependencyTarget.Package) }); // Create fake projects, the real data is in the specs var projects = CreateProjectsFromSpecs(pathContext, spec); // Create dg file var dgFile = new DependencyGraphSpec(); dgFile.AddProject(spec); dgFile.AddRestore(spec.RestoreMetadata.ProjectUniqueName); dgFile.Save(Path.Combine(pathContext.WorkingDirectory, "out.dg")); var packageX = new SimpleTestPackageContext() { Id = "x", Version = "1.0.0" }; packageX.AddFile("build/x.targets"); packageX.AddFile("build/x.props"); packageX.AddFile("contentFiles/any/any/_._"); await SimpleTestPackageUtility.CreatePackagesAsync(pathContext.PackageSource, packageX); var project = projects[0]; // Act var summaries = await RunRestoreAsync(pathContext, logger, sources, dgFile, cacheContext); var success = summaries.All(s => s.Success); // Assert Assert.True(success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); var targetsXML = XDocument.Parse(File.ReadAllText(project.TargetsOutput)); var targetItemGroups = targetsXML.Root.Elements().Where(e => e.Name.LocalName == "ImportGroup").ToList(); var propsXML = XDocument.Parse(File.ReadAllText(project.PropsOutput)); var propsItemGroups = propsXML.Root.Elements().Where(e => e.Name.LocalName == "ImportGroup").ToList(); Assert.Equal("'$(ExcludeRestorePackageImports)' != 'true'", targetItemGroups[0].Attribute(XName.Get("Condition")).Value.Trim()); Assert.Equal("'$(ExcludeRestorePackageImports)' != 'true'", propsItemGroups[0].Attribute(XName.Get("Condition")).Value.Trim()); } }
public void Json_WhenDgSpecWasCreatedWithBoolConstructor_ReturnsEmptyObject() { var dgSpec = new DependencyGraphSpec(isReadOnly: true); Assert.Empty(dgSpec.Json); }
/// <summary> /// Restores a package by querying, downloading, and unzipping it without generating any other files (like project.assets.json). /// </summary> /// <param name="projectPath">The full path to the project.</param> /// <param name="id">The ID of the package.</param> /// <param name="version">The version of the package.</param> /// <param name="settings">The NuGet settings to use.</param> /// <param name="logger">An <see cref="ILogger"/> to use for logging.</param> /// <returns></returns> public static Task <IReadOnlyList <RestoreResultPair> > RunWithoutCommit(string projectPath, string id, string version, ISettings settings, ILogger logger) { using (SourceCacheContext sourceCacheContext = new SourceCacheContext { IgnoreFailedSources = true, }) { // The package spec details what packages to restore PackageSpec packageSpec = new PackageSpec(TargetFrameworks.Select(i => new TargetFrameworkInformation { FrameworkName = i, }).ToList()) { Dependencies = new List <LibraryDependency> { new LibraryDependency { LibraryRange = new LibraryRange(id, new VersionRange(NuGetVersion.Parse(version)), LibraryDependencyTarget.Package), SuppressParent = LibraryIncludeFlags.All, AutoReferenced = true, IncludeType = LibraryIncludeFlags.None, Type = LibraryDependencyType.Build } }, RestoreMetadata = new ProjectRestoreMetadata { ProjectPath = projectPath, ProjectName = Path.GetFileNameWithoutExtension(projectPath), ProjectStyle = ProjectStyle.PackageReference, ProjectUniqueName = projectPath, OutputPath = Path.GetTempPath(), OriginalTargetFrameworks = TargetFrameworks.Select(i => i.ToString()).ToList(), ConfigFilePaths = SettingsUtility.GetConfigFilePaths(settings).ToList(), PackagesPath = SettingsUtility.GetGlobalPackagesFolder(settings), Sources = SettingsUtility.GetEnabledSources(settings).ToList(), FallbackFolders = SettingsUtility.GetFallbackPackageFolders(settings).ToList() }, FilePath = projectPath, Name = Path.GetFileNameWithoutExtension(projectPath), }; DependencyGraphSpec dependencyGraphSpec = new DependencyGraphSpec(); dependencyGraphSpec.AddProject(packageSpec); dependencyGraphSpec.AddRestore(packageSpec.RestoreMetadata.ProjectUniqueName); IPreLoadedRestoreRequestProvider requestProvider = new DependencyGraphSpecRequestProvider(new RestoreCommandProvidersCache(), dependencyGraphSpec); RestoreArgs restoreArgs = new RestoreArgs { AllowNoOp = true, CacheContext = sourceCacheContext, CachingSourceProvider = new CachingSourceProvider(new PackageSourceProvider(settings)), Log = logger, }; // Create requests from the arguments IReadOnlyList <RestoreSummaryRequest> requests = requestProvider.CreateRequests(restoreArgs).Result; // Restore the package without generating extra files return(RestoreRunner.RunWithoutCommit(requests, restoreArgs)); } }
public static async Task <(RestoreRequest, RestoreResult)> Restore(ILogger logger, NuGetFramework nugetFramework, string runtimeIdentifier, string packageName, VersionRange versionRange) { var settings = NuGet.Configuration.Settings.LoadDefaultSettings(null); var assemblies = new List <string>(); var projectPath = Path.Combine("StrideNugetResolver.json"); var spec = new PackageSpec() { Name = Path.GetFileNameWithoutExtension(projectPath), // make sure this package never collides with a dependency FilePath = projectPath, Dependencies = new List <LibraryDependency>() { new LibraryDependency { LibraryRange = new LibraryRange(packageName, versionRange, LibraryDependencyTarget.Package), } }, TargetFrameworks = { new TargetFrameworkInformation { FrameworkName = nugetFramework, } }, RestoreMetadata = new ProjectRestoreMetadata { ProjectPath = projectPath, ProjectName = Path.GetFileNameWithoutExtension(projectPath), ProjectStyle = ProjectStyle.PackageReference, ProjectUniqueName = projectPath, OutputPath = Path.Combine(Path.GetTempPath(), $"StrideNugetResolver-{packageName}-{versionRange.MinVersion.ToString()}-{nugetFramework.GetShortFolderName()}-{runtimeIdentifier}"), OriginalTargetFrameworks = new[] { nugetFramework.GetShortFolderName() }, ConfigFilePaths = settings.GetConfigFilePaths(), PackagesPath = SettingsUtility.GetGlobalPackagesFolder(settings), Sources = SettingsUtility.GetEnabledSources(settings).ToList(), FallbackFolders = SettingsUtility.GetFallbackPackageFolders(settings).ToList() }, RuntimeGraph = new RuntimeGraph(new[] { new RuntimeDescription(runtimeIdentifier) }), }; using (var context = new SourceCacheContext()) { context.IgnoreFailedSources = true; var dependencyGraphSpec = new DependencyGraphSpec(); dependencyGraphSpec.AddProject(spec); dependencyGraphSpec.AddRestore(spec.RestoreMetadata.ProjectUniqueName); IPreLoadedRestoreRequestProvider requestProvider = new DependencyGraphSpecRequestProvider(new RestoreCommandProvidersCache(), dependencyGraphSpec); var restoreArgs = new RestoreArgs { AllowNoOp = true, CacheContext = context, CachingSourceProvider = new CachingSourceProvider(new PackageSourceProvider(settings)), Log = logger, }; // Create requests from the arguments var requests = requestProvider.CreateRequests(restoreArgs).Result; // Restore the packages for (int tryCount = 0; tryCount < 2; ++tryCount) { try { var results = await RestoreRunner.RunWithoutCommit(requests, restoreArgs); // Commit results so that noop cache works next time foreach (var result in results) { await result.Result.CommitAsync(logger, CancellationToken.None); } var mainResult = results.First(); return(mainResult.SummaryRequest.Request, mainResult.Result); } catch (Exception e) when(e is UnauthorizedAccessException || e is IOException) { // If we have an unauthorized access exception, it means assemblies are locked by running Stride process // During first try, kill some known harmless processes, and try again if (tryCount == 1) { throw; } foreach (var process in new[] { "Stride.ConnectionRouter" }.SelectMany(Process.GetProcessesByName)) { try { if (process.Id != Process.GetCurrentProcess().Id) { process.Kill(); process.WaitForExit(); } } catch (Exception) { } } } } throw new InvalidOperationException("Unreachable code"); } }
/****************** * ToolReferences * ******************/ internal static void ProcessToolReferences(ProjectNames projectNames, IEnumerable targetFrameworks, IVsReferenceItems toolReferences, DependencyGraphSpec dgSpec) { var toolFramework = GetToolFramework(targetFrameworks); var packagesPath = GetRestoreProjectPath(targetFrameworks); var fallbackFolders = GetRestoreFallbackFolders(targetFrameworks).AsList(); var sources = GetRestoreSources(targetFrameworks) .Select(e => new PackageSource(e)) .ToList(); toolReferences .Cast <IVsReferenceItem>() .Select(r => ToolRestoreUtility.GetSpec( projectNames.FullName, r.Name, GetVersionRange(r), toolFramework, packagesPath, fallbackFolders, sources, projectWideWarningProperties: null)) .ForEach(ts => { dgSpec.AddRestore(ts.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(ts); }); }
private void AddInputsFromDependencyGraphSpec(PackageRestoreInputs packageRestoreInputs, DependencyGraphSpec dgFileOutput) { packageRestoreInputs.ProjectReferenceLookup = dgFileOutput; // Get top level entries var entryPointProjects = dgFileOutput .Projects .Where(project => dgFileOutput.Restore.Contains(project.RestoreMetadata.ProjectUniqueName, StringComparer.Ordinal)) .ToList(); // possible packages.config // Compare paths case-insenstive here since we do not know how msbuild modified them // find all projects that are not part of the v3 group var v2RestoreProjects = packageRestoreInputs.ProjectFiles .Where(path => !entryPointProjects.Any(project => path.Equals(project.RestoreMetadata.ProjectPath, StringComparison.OrdinalIgnoreCase))); packageRestoreInputs.PackagesConfigFiles .AddRange(v2RestoreProjects .Select(GetPackagesConfigFile) .Where(path => path != null)); // Filter down to just the requested projects in the file // that support transitive references. var v3RestoreProjects = dgFileOutput.Projects .Where(project => (project.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference || project.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson) && entryPointProjects.Contains(project)); packageRestoreInputs.RestoreV3Context.Inputs.AddRange(v3RestoreProjects .Select(project => project.RestoreMetadata.ProjectPath)); }
/// <summary> /// Persists the dg file for the given restore request. /// This does not do a dirty check! /// </summary> /// <param name="spec">spec</param> /// <param name="dgPath">the dg path</param> /// <param name="log">logger</param> internal static void PersistDGSpecFile(DependencyGraphSpec spec, string dgPath, ILogger log) { Directory.CreateDirectory(Path.GetDirectoryName(dgPath)); log.LogVerbose($"Persisting no-op dg to {dgPath}"); spec.Save(dgPath); }
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)); } }
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")); } }
private IReadOnlyList <RestoreSummaryRequest> GetRequestsFromItems(RestoreArgs restoreContext, DependencyGraphSpec dgFile) { if (restoreContext == null) { throw new ArgumentNullException(nameof(restoreContext)); } if (dgFile == null) { throw new ArgumentNullException(nameof(dgFile)); } // Validate the dg file input, this throws if errors are found. SpecValidationUtility.ValidateDependencySpec(dgFile); // Create requests var requests = new List <RestoreSummaryRequest>(); var toolRequests = new List <RestoreSummaryRequest>(); foreach (var projectNameToRestore in dgFile.Restore) { var closure = dgFile.GetClosure(projectNameToRestore); var projectDependencyGraphSpec = dgFile.WithProjectClosure(projectNameToRestore); var externalClosure = new HashSet <ExternalProjectReference>(closure.Select(GetExternalProject)); var rootProject = externalClosure.Single(p => StringComparer.Ordinal.Equals(projectNameToRestore, p.UniqueName)); var request = Create(projectNameToRestore, rootProject, externalClosure, restoreContext, projectDgSpec: projectDependencyGraphSpec); if (request.Request.ProjectStyle == ProjectStyle.DotnetCliTool) { // Store tool requests to be filtered later toolRequests.Add(request); } else { requests.Add(request); } } // Filter out duplicate tool restore requests requests.AddRange(ToolRestoreUtility.GetSubSetRequests(toolRequests)); return(requests); }
/// <summary> /// Fetch, if not already downloaded, and install the package represented by /// (<paramref name="packageId"/>, <paramref name="version"/>). /// </summary> /// <remarks>It is safe to call it concurrently be cause we operations are done using the FileLock.</remarks> /// <param name="packageId">Name of package to install.</param> /// <param name="version">Version of package to install.</param> public async Task <NugetLocalPackage> InstallPackage(string packageId, PackageVersion version, ProgressReport progress) { using (GetLocalRepositoryLock()) { currentProgressReport = progress; try { var identity = new PackageIdentity(packageId, version.ToNuGetVersion()); var resolutionContext = new ResolutionContext( DependencyBehavior.Lowest, true, true, VersionConstraints.None); var repositories = PackageSources.Select(sourceRepositoryProvider.CreateRepository).ToArray(); var projectContext = new EmptyNuGetProjectContext() { ActionType = NuGetActionType.Install, PackageExtractionContext = new PackageExtractionContext(PackageSaveMode.Defaultv3, XmlDocFileSaveMode.Skip, null, NativeLogger), }; ActivityCorrelationId.StartNew(); { var installPath = SettingsUtility.GetGlobalPackagesFolder(settings); // Old version expects to be installed in GamePackages if (packageId == "Xenko" && version < new PackageVersion(3, 0, 0, 0) && oldRootDirectory != null) { installPath = oldRootDirectory; } var projectPath = Path.Combine("StrideLauncher.json"); var spec = new PackageSpec() { Name = Path.GetFileNameWithoutExtension(projectPath), // make sure this package never collides with a dependency FilePath = projectPath, Dependencies = new List <LibraryDependency>() { new LibraryDependency { LibraryRange = new LibraryRange(packageId, new VersionRange(version.ToNuGetVersion()), LibraryDependencyTarget.Package), } }, TargetFrameworks = { new TargetFrameworkInformation { FrameworkName = NuGetFramework.Parse("net472"), } }, RestoreMetadata = new ProjectRestoreMetadata { ProjectPath = projectPath, ProjectName = Path.GetFileNameWithoutExtension(projectPath), ProjectStyle = ProjectStyle.PackageReference, ProjectUniqueName = projectPath, OutputPath = Path.Combine(Path.GetTempPath(), $"StrideLauncher-{packageId}-{version.ToString()}"), OriginalTargetFrameworks = new[] { "net472" }, ConfigFilePaths = settings.GetConfigFilePaths(), PackagesPath = installPath, Sources = SettingsUtility.GetEnabledSources(settings).ToList(), FallbackFolders = SettingsUtility.GetFallbackPackageFolders(settings).ToList() }, }; using (var context = new SourceCacheContext { MaxAge = DateTimeOffset.UtcNow }) { context.IgnoreFailedSources = true; var dependencyGraphSpec = new DependencyGraphSpec(); dependencyGraphSpec.AddProject(spec); dependencyGraphSpec.AddRestore(spec.RestoreMetadata.ProjectUniqueName); IPreLoadedRestoreRequestProvider requestProvider = new DependencyGraphSpecRequestProvider(new RestoreCommandProvidersCache(), dependencyGraphSpec); var restoreArgs = new RestoreArgs { AllowNoOp = true, CacheContext = context, CachingSourceProvider = new CachingSourceProvider(new PackageSourceProvider(settings)), Log = NativeLogger, }; // Create requests from the arguments var requests = requestProvider.CreateRequests(restoreArgs).Result; foreach (var request in requests) { // Limit concurrency to avoid timeout request.Request.MaxDegreeOfConcurrency = 4; var command = new RestoreCommand(request.Request); // Act var result = await command.ExecuteAsync(); if (!result.Success) { throw new InvalidOperationException($"Could not restore package {packageId}"); } foreach (var install in result.RestoreGraphs.Last().Install) { var package = result.LockFile.Libraries.FirstOrDefault(x => x.Name == install.Library.Name && x.Version == install.Library.Version); if (package != null) { var packagePath = Path.Combine(installPath, package.Path); OnPackageInstalled(this, new PackageOperationEventArgs(new PackageName(install.Library.Name, install.Library.Version.ToPackageVersion()), packagePath)); } } } } if (packageId == "Xenko" && version < new PackageVersion(3, 0, 0, 0)) { UpdateTargetsHelper(); } } // Load the recently installed package var installedPackages = GetPackagesInstalled(new[] { packageId }); return(installedPackages.FirstOrDefault(p => p.Version == version)); } finally { currentProgressReport = null; } } }
// The algorithm here is a 2 pass. In reality the 2nd pass can do a lot but for huge benefits :) // Pass #1 // We check all the specs against the cached ones if any. Any project with a change in the spec is considered dirty. // If a project had previously been restored and it failed, it is considered dirty. // Every project that is considered to have a dirty spec will be important in pass #2. // In the first pass, we also validate the outputs for the projects. Note that these are independent and project specific. Outputs not being up to date it irrelevant for transitivity. // Pass #2 // For every project with a dirty spec (the outputs don't matter here), we want to ensure that its parent projects are marked as dirty as well. // This is a bit more expensive since PackageSpecs do not retain pointers to the projects that reference them as ProjectReference. // Finally we only update the cache specs if Pass #1 determined that there are projects that are not up to date. // Result // Lastly all the projects marked as having dirty specs & dirty outputs are returned. // Before we return the list of projects that are not up to date, we always make sure to replay the warnings for the up to date projects. public IEnumerable <string> PerformUpToDateCheck(DependencyGraphSpec dependencyGraphSpec, ILogger logger) { if (dependencyGraphSpec == null) { throw new ArgumentNullException(nameof(dependencyGraphSpec)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (_cachedDependencyGraphSpec != null) { var dirtySpecs = new List <string>(); var dirtyOutputs = new List <string>(); bool hasDirtyNonTransitiveSpecs = false; // Pass #1. Validate all the data (i/o) // 1a. Validate the package specs (references & settings) // 1b. Validate the expected outputs (assets file, nuget.g.*, lock file) var unloadedProjects = _restoreData.Keys.ToHashSet(); foreach (var project in dependencyGraphSpec.Projects) { var projectUniqueName = project.RestoreMetadata.ProjectUniqueName; var cache = _cachedDependencyGraphSpec.GetProjectSpec(projectUniqueName); if (cache == null || !project.Equals(cache)) { dirtySpecs.Add(projectUniqueName); } unloadedProjects.Remove(projectUniqueName); if (project.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference || project.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson) { if (!_failedProjects.Contains(projectUniqueName) && _restoreData.TryGetValue(projectUniqueName, out RestoreData restoreData)) { GetOutputFilePaths(project, out string assetsFilePath, out string cacheFilePath, out string targetsFilePath, out string propsFilePath, out string lockFilePath); if (!AreOutputsUpToDate(assetsFilePath, cacheFilePath, targetsFilePath, propsFilePath, lockFilePath, project.RestoreMetadata.PackagesPath, restoreData)) { dirtyOutputs.Add(projectUniqueName); } } else { dirtyOutputs.Add(projectUniqueName); } } else { hasDirtyNonTransitiveSpecs = true; } } // Remove the cached data of the unloaded projects if any. foreach (var project in unloadedProjects) { _restoreData.Remove(project); } // Fast path. Skip Pass #2 if (dirtySpecs.Count == 0 && dirtyOutputs.Count == 0) { ReplayAllWarnings(_restoreData, (string projectName) => true, logger); return(Enumerable.Empty <string>()); } // Update the cache before Pass #2 _cachedDependencyGraphSpec = dependencyGraphSpec; // Pass #2 For any dirty specs discrepancies, mark them and their parents as needing restore. var dirtyProjects = GetParents(dirtySpecs, dependencyGraphSpec); // All dirty projects + projects with outputs that need to be restored // - the projects that are non transitive that never needed restore anyways, hence the intersection with the provider restore projects! var resultSpecs = dirtyProjects.Union(dirtyOutputs); if (hasDirtyNonTransitiveSpecs) { resultSpecs = dependencyGraphSpec.Restore.Intersect(resultSpecs); } ReplayAllWarnings(_restoreData, (string projectName) => !resultSpecs.Contains(projectName), logger); return(resultSpecs); } else { _cachedDependencyGraphSpec = dependencyGraphSpec; return(dependencyGraphSpec.Restore); } }
private static async Task <RestoreSummary> PerformNuGetV2RestoreAsync(Common.ILogger log, DependencyGraphSpec dgFile, bool noCache, bool disableParallel, bool interactive) { string globalPackageFolder = null; string repositoryPath = null; string firstPackagesConfigPath = null; IList <PackageSource> packageSources = null; var installedPackageReferences = new HashSet <Packaging.PackageReference>(new PackageReferenceComparer()); ISettings settings = null; foreach (PackageSpec packageSpec in dgFile.Projects.Where(i => i.RestoreMetadata.ProjectStyle == ProjectStyle.PackagesConfig)) { var pcRestoreMetadata = (PackagesConfigProjectRestoreMetadata)packageSpec.RestoreMetadata; globalPackageFolder = globalPackageFolder ?? pcRestoreMetadata.PackagesPath; repositoryPath = repositoryPath ?? pcRestoreMetadata.RepositoryPath; if (packageSources == null) { packageSources = new List <PackageSource>(); if (!noCache) { if (!string.IsNullOrEmpty(globalPackageFolder) && Directory.Exists(globalPackageFolder)) { packageSources.Add(new FeedTypePackageSource(globalPackageFolder, FeedType.FileSystemV3)); } } packageSources.AddRange(pcRestoreMetadata.Sources); } settings = settings ?? Settings.LoadSettingsGivenConfigPaths(pcRestoreMetadata.ConfigFilePaths); var packagesConfigPath = Path.Combine(Path.GetDirectoryName(pcRestoreMetadata.ProjectPath), NuGetConstants.PackageReferenceFile); firstPackagesConfigPath = firstPackagesConfigPath ?? packagesConfigPath; installedPackageReferences.AddRange(GetInstalledPackageReferences(packagesConfigPath, allowDuplicatePackageIds: true)); } if (string.IsNullOrEmpty(repositoryPath)) { throw new InvalidOperationException(Strings.RestoreNoSolutionFound); } PackageSourceProvider packageSourceProvider = new PackageSourceProvider(settings); var sourceRepositoryProvider = new CachingSourceProvider(packageSourceProvider); var nuGetPackageManager = new NuGetPackageManager(sourceRepositoryProvider, settings, repositoryPath); var effectivePackageSaveMode = CalculateEffectivePackageSaveMode(settings); var packageSaveMode = effectivePackageSaveMode == Packaging.PackageSaveMode.None ? Packaging.PackageSaveMode.Defaultv2 : effectivePackageSaveMode; var missingPackageReferences = installedPackageReferences.Where(reference => !nuGetPackageManager.PackageExistsInPackagesFolder(reference.PackageIdentity, packageSaveMode)).ToArray(); if (missingPackageReferences.Length == 0) { return(new RestoreSummary(true)); } var packageRestoreData = missingPackageReferences.Select(reference => new PackageRestoreData( reference, new[] { firstPackagesConfigPath }, isMissing: true)); var repositories = sourceRepositoryProvider.GetRepositories().ToArray(); var installCount = 0; var failedEvents = new ConcurrentQueue <PackageRestoreFailedEventArgs>(); var collectorLogger = new RestoreCollectorLogger(log); var packageRestoreContext = new PackageRestoreContext( nuGetPackageManager, packageRestoreData, CancellationToken.None, packageRestoredEvent: (sender, args) => { Interlocked.Add(ref installCount, args.Restored ? 1 : 0); }, packageRestoreFailedEvent: (sender, args) => { failedEvents.Enqueue(args); }, sourceRepositories: repositories, maxNumberOfParallelTasks: disableParallel ? 1 : PackageManagementConstants.DefaultMaxDegreeOfParallelism, logger: collectorLogger); // TODO: Check require consent? // NOTE: This feature is currently not working at all. See https://github.com/NuGet/Home/issues/4327 // CheckRequireConsent(); var clientPolicyContext = ClientPolicyContext.GetClientPolicy(settings, collectorLogger); var projectContext = new ConsoleProjectContext(collectorLogger) { PackageExtractionContext = new PackageExtractionContext( packageSaveMode, PackageExtractionBehavior.XmlDocFileSaveMode, clientPolicyContext, collectorLogger) }; if (effectivePackageSaveMode != Packaging.PackageSaveMode.None) { projectContext.PackageExtractionContext.PackageSaveMode = packageSaveMode; } using (var cacheContext = new SourceCacheContext()) { cacheContext.NoCache = noCache; var packageSourceMapping = PackageSourceMapping.GetPackageSourceMapping(settings); var downloadContext = new PackageDownloadContext(cacheContext, repositoryPath, directDownload: false, packageSourceMapping) { ClientPolicyContext = clientPolicyContext }; DefaultCredentialServiceUtility.SetupDefaultCredentialService(log, !interactive); var result = await PackageRestoreManager.RestoreMissingPackagesAsync( packageRestoreContext, projectContext, downloadContext); return(new RestoreSummary( result.Restored, "packages.config projects", settings.GetConfigFilePaths().ToArray(), packageSources.Select(x => x.Source).ToArray(), installCount, collectorLogger.Errors.Concat(ProcessFailedEventsIntoRestoreLogs(failedEvents)).ToArray() )); } }
public static async Task <bool> RestoreAsync( DependencyGraphSpec dependencyGraphSpec, bool interactive, bool recursive, bool noCache, bool ignoreFailedSources, bool disableParallel, bool force, bool forceEvaluate, bool hideWarningsAndErrors, bool restorePC, bool cleanupAssetsForUnsupportedProjects, Common.ILogger log, CancellationToken cancellationToken) { if (dependencyGraphSpec == null) { throw new ArgumentNullException(nameof(dependencyGraphSpec)); } if (log == null) { throw new ArgumentNullException(nameof(log)); } try { DefaultCredentialServiceUtility.SetupDefaultCredentialService(log, !interactive); // Set connection limit NetworkProtocolUtility.SetConnectionLimit(); // Set user agent string used for network calls #if IS_CORECLR UserAgent.SetUserAgentString(new UserAgentStringBuilder("NuGet .NET Core MSBuild Task") .WithOSDescription(RuntimeInformation.OSDescription)); #else // OS description is set by default on Desktop UserAgent.SetUserAgentString(new UserAgentStringBuilder("NuGet Desktop MSBuild Task")); #endif X509TrustStore.InitializeForDotNetSdk(log); var restoreSummaries = new List <RestoreSummary>(); var providerCache = new RestoreCommandProvidersCache(); #if IS_DESKTOP if (restorePC && dependencyGraphSpec.Projects.Any(i => i.RestoreMetadata.ProjectStyle == ProjectStyle.PackagesConfig)) { var v2RestoreResult = await PerformNuGetV2RestoreAsync(log, dependencyGraphSpec, noCache, disableParallel, interactive); restoreSummaries.Add(v2RestoreResult); if (restoreSummaries.Count < 1) { var message = string.Format( Strings.InstallCommandNothingToInstall, "packages.config" ); log.LogMinimal(message); } if (!v2RestoreResult.Success) { v2RestoreResult .Errors .Where(l => l.Level == LogLevel.Warning) .ForEach(message => { log.LogWarning(message.Message); }); } } #endif using (var cacheContext = new SourceCacheContext()) { cacheContext.NoCache = noCache; cacheContext.IgnoreFailedSources = ignoreFailedSources; // Pre-loaded request provider containing the graph file var providers = new List <IPreLoadedRestoreRequestProvider>(); if (dependencyGraphSpec.Restore.Count > 0) { // Add all child projects if (recursive) { AddAllProjectsForRestore(dependencyGraphSpec); } providers.Add(new DependencyGraphSpecRequestProvider(providerCache, dependencyGraphSpec)); var restoreContext = new RestoreArgs() { CacheContext = cacheContext, LockFileVersion = LockFileFormat.Version, // 'dotnet restore' fails on slow machines (https://github.com/NuGet/Home/issues/6742) // The workaround is to pass the '--disable-parallel' option. // We apply the workaround by default when the system has 1 cpu. // This will fix restore failures on VMs with 1 CPU and containers with less or equal to 1 CPU assigned. DisableParallel = Environment.ProcessorCount == 1 ? true : disableParallel, Log = log, MachineWideSettings = new XPlatMachineWideSetting(), PreLoadedRequestProviders = providers, AllowNoOp = !force, HideWarningsAndErrors = hideWarningsAndErrors, RestoreForceEvaluate = forceEvaluate }; if (restoreContext.DisableParallel) { HttpSourceResourceProvider.Throttle = SemaphoreSlimThrottle.CreateBinarySemaphore(); } cancellationToken.ThrowIfCancellationRequested(); restoreSummaries.AddRange(await RestoreRunner.RunAsync(restoreContext, cancellationToken)); } if (cleanupAssetsForUnsupportedProjects) { // Restore assets are normally left on disk between restores for all projects. This can cause a condition where a project that supports PackageReference was restored // but then a user changes a branch or some other condition and now the project does not use PackageReference. Since the restore assets are left on disk, the build // consumes them which can cause build errors. The code below cleans up all of the files that we write so that they are not used during build Parallel.ForEach(dependencyGraphSpec.Projects.Where(i => !DoesProjectSupportRestore(i)), project => { if (project.RestoreMetadata == null || string.IsNullOrWhiteSpace(project.RestoreMetadata.OutputPath) || string.IsNullOrWhiteSpace(project.RestoreMetadata.ProjectPath)) { return; } // project.assets.json FileUtility.Delete(Path.Combine(project.RestoreMetadata.OutputPath, LockFileFormat.AssetsFileName)); // project.csproj.nuget.cache FileUtility.Delete(project.RestoreMetadata.CacheFilePath); // project.csproj.nuget.g.props FileUtility.Delete(BuildAssetsUtils.GetMSBuildFilePathForPackageReferenceStyleProject(project, BuildAssetsUtils.PropsExtension)); // project..csproj.nuget.g.targets FileUtility.Delete(BuildAssetsUtils.GetMSBuildFilePathForPackageReferenceStyleProject(project, BuildAssetsUtils.TargetsExtension)); // project.csproj.nuget.dgspec.json FileUtility.Delete(Path.Combine(project.RestoreMetadata.OutputPath, DependencyGraphSpec.GetDGSpecFileName(Path.GetFileName(project.RestoreMetadata.ProjectPath)))); }); } } if (restoreSummaries.Count < 1) { log.LogMinimal(Strings.NoProjectsToRestore); } else { RestoreSummary.Log(log, restoreSummaries); } return(restoreSummaries.All(x => x.Success)); } finally { // The CredentialService lifetime is for the duration of the process. We should not leave a potentially unavailable logger. // We need to update the delegating logger with a null instance // because the tear downs of the plugins and similar rely on idleness and process exit. DefaultCredentialServiceUtility.UpdateCredentialServiceDelegatingLogger(NullLogger.Instance); } }
public static void NormalizePathCasings(Dictionary <string, string> paths, DependencyGraphSpec graphSpec) { NormalizePathCasings((IDictionary <string, string>)paths, graphSpec); }
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"), 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); foreach (var version in versions) { await SimpleTestPackageUtility.CreateFolderFeedV3Async(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), $"{path} does not exist!"); } } }
/// <summary> /// Returns the closure of project references for projects specified in <paramref name="projectPaths"/>. /// </summary> public static async Task <DependencyGraphSpec> GetProjectReferencesAsync( MsBuildToolset msbuildToolset, string[] projectPaths, int timeOut, IConsole console, bool recursive, string solutionDirectory, string solutionName, string restoreConfigFile, string[] sources, string packagesDirectory, RestoreLockProperties restoreLockProperties) { var msbuildPath = GetMsbuild(msbuildToolset.Path); if (!File.Exists(msbuildPath)) { throw new CommandException( string.Format( CultureInfo.CurrentCulture, LocalizedResourceManager.GetString(nameof(NuGetResources.MsBuildDoesNotExistAtPath)), msbuildPath)); } var nugetExePath = Assembly.GetEntryAssembly().Location; // Check for the non-ILMerged path var buildTasksPath = Path.Combine(Path.GetDirectoryName(nugetExePath), "NuGet.Build.Tasks.dll"); if (File.Exists(buildTasksPath)) { nugetExePath = buildTasksPath; } using (var inputTargetPath = new TempFile(".nugetinputs.targets")) using (var entryPointTargetPath = new TempFile(".nugetrestore.targets")) using (var resultsPath = new TempFile(".output.dg")) { // Read NuGet.targets from nuget.exe and write it to disk for msbuild.exe ExtractResource(NuGetTargets, entryPointTargetPath); // Build a .targets file of all restore inputs, this is needed to avoid going over the limit on command line arguments. var properties = new Dictionary <string, string>() { { "RestoreUseCustomAfterTargets", "true" }, { "RestoreGraphOutputPath", resultsPath }, { "RestoreRecursive", recursive.ToString().ToLowerInvariant() }, { "RestoreProjectFilterMode", "exclusionlist" } }; var inputTargetXML = GetRestoreInputFile(entryPointTargetPath, properties, projectPaths); inputTargetXML.Save(inputTargetPath); // Create msbuild parameters and include global properties that cannot be set in the input targets path var arguments = GetMSBuildArguments(entryPointTargetPath, inputTargetPath, nugetExePath, solutionDirectory, solutionName, restoreConfigFile, sources, packagesDirectory, msbuildToolset, restoreLockProperties, EnvironmentVariableWrapper.Instance); var processStartInfo = new ProcessStartInfo { UseShellExecute = false, FileName = msbuildPath, Arguments = arguments, RedirectStandardError = true, RedirectStandardOutput = true }; console.LogDebug($"{processStartInfo.FileName} {processStartInfo.Arguments}"); using (var process = Process.Start(processStartInfo)) { var errors = new StringBuilder(); var output = new StringBuilder(); var excluded = new string[] { "msb4011", entryPointTargetPath }; // Read console output var errorTask = ConsumeStreamReaderAsync(process.StandardError, errors, filter: null); var outputTask = ConsumeStreamReaderAsync(process.StandardOutput, output, filter: (line) => IsIgnoredOutput(line, excluded)); // Run msbuild var finished = process.WaitForExit(timeOut); // Handle timeouts if (!finished) { try { process.Kill(); } catch (Exception ex) { throw new CommandException( LocalizedResourceManager.GetString(nameof(NuGetResources.Error_CannotKillMsBuild)) + " : " + ex.Message, ex); } } // Read all console output from msbuild. await Task.WhenAll(outputTask, errorTask); // By default log msbuild output so that it is only // displayed under -Verbosity detailed var logLevel = LogLevel.Verbose; if (process.ExitCode != 0 || !finished) { // If a problem occurred log all msbuild output as an error // so that the user can see it. // By default this runs with /v:q which means that only // errors and warnings will be in the output. logLevel = LogLevel.Error; } // MSBuild writes errors to the output stream, parsing the console output to find // the errors would be error prone so here we log all output combined with any // errors on the error stream (haven't seen the error stream used to date) // to give the user the complete info. await console.LogAsync(logLevel, output.ToString() + errors.ToString()); if (!finished) { // MSBuild timed out throw new CommandException( LocalizedResourceManager.GetString(nameof(NuGetResources.Error_MsBuildTimedOut))); } await outputTask; if (process.ExitCode != 0) { // Do not continue if msbuild failed. throw new ExitCodeException(1); } } DependencyGraphSpec spec = null; if (File.Exists(resultsPath) && new FileInfo(resultsPath).Length != 0) { spec = DependencyGraphSpec.Load(resultsPath); File.Delete(resultsPath); } else { spec = new DependencyGraphSpec(); } return(spec); } }
public async Task RestoreRunner_BasicRestore_VerifyFailureWritesFiles_NETCore() { // Arrange var sources = new List <PackageSource>(); var project1Json = @" { ""version"": ""1.0.0"", ""description"": """", ""authors"": [ ""author"" ], ""tags"": [ """" ], ""projectUrl"": """", ""licenseUrl"": """", ""frameworks"": { ""net45"": { ""dependencies"": { ""x"": ""1.0.0"" } } } }"; using (var workingDir = TestDirectory.Create()) { var packagesDir = new DirectoryInfo(Path.Combine(workingDir, "globalPackages")); var packageSource = new DirectoryInfo(Path.Combine(workingDir, "packageSource")); var project1 = new DirectoryInfo(Path.Combine(workingDir, "projects", "project1")); packagesDir.Create(); packageSource.Create(); project1.Create(); sources.Add(new PackageSource(packageSource.FullName)); File.WriteAllText(Path.Combine(project1.FullName, "project.json"), project1Json); var specPath1 = Path.Combine(project1.FullName, "project.json"); var spec1 = JsonPackageSpecReader.GetPackageSpec(project1Json, "project1", specPath1); spec1.RestoreMetadata = new ProjectRestoreMetadata(); spec1.RestoreMetadata.OutputPath = Path.Combine(project1.FullName, "obj"); spec1.RestoreMetadata.ProjectStyle = ProjectStyle.PackageReference; spec1.RestoreMetadata.ProjectName = "project1"; spec1.RestoreMetadata.ProjectPath = Path.Combine(project1.FullName, "project1.csproj"); spec1.RestoreMetadata.ProjectUniqueName = spec1.RestoreMetadata.ProjectPath; spec1.RestoreMetadata.TargetFrameworks.Add(new ProjectRestoreMetadataFrameworkInfo(NuGetFramework.Parse("net45"))); spec1.RestoreMetadata.OriginalTargetFrameworks.Add("net45"); spec1.FilePath = spec1.RestoreMetadata.ProjectPath; var dgSpec = new DependencyGraphSpec(); dgSpec.AddProject(spec1); dgSpec.AddRestore(spec1.RestoreMetadata.ProjectUniqueName); var logger = new TestLogger(); var assetsPath = Path.Combine(project1.FullName, "obj", "project.assets.json"); var sourceRepos = sources.Select(source => Repository.Factory.GetCoreV3(source.Source)).ToList(); var providerCache = new RestoreCommandProvidersCache(); using (var cacheContext = new SourceCacheContext()) { var restoreContext = new RestoreArgs() { CacheContext = cacheContext, DisableParallel = true, GlobalPackagesFolder = packagesDir.FullName, Sources = new List <string>() { packageSource.FullName }, Log = logger, CachingSourceProvider = new CachingSourceProvider(new TestPackageSourceProvider(sources)), PreLoadedRequestProviders = new List <IPreLoadedRestoreRequestProvider>() { new DependencyGraphSpecRequestProvider(providerCache, dgSpec) } }; // Act var summaries = await RestoreRunner.Run(restoreContext); var summary = summaries.Single(); // Assert Assert.False(summary.Success); Assert.True(File.Exists(assetsPath), assetsPath); Assert.True(File.Exists(Path.Combine(project1.FullName, "obj", "project1.csproj.nuget.g.props"))); Assert.True(File.Exists(Path.Combine(project1.FullName, "obj", "project1.csproj.nuget.g.targets"))); } } }
public PackageRestoreInputs() { ProjectReferenceLookup = new DependencyGraphSpec(); }
public async Task RestoreRunner_RestoreWithExternalFile_NetCoreOutput() { // Arrange var sources = new List <PackageSource>(); var targetFrameworkInfo1 = new TargetFrameworkInformation(); targetFrameworkInfo1.FrameworkName = NuGetFramework.Parse("net45"); var frameworks1 = new[] { targetFrameworkInfo1 }; var targetFrameworkInfo2 = new TargetFrameworkInformation(); targetFrameworkInfo2.FrameworkName = NuGetFramework.Parse("net45"); var frameworks2 = new[] { targetFrameworkInfo2 }; // Create two net45 projects var spec1 = new PackageSpec(frameworks1); spec1.RestoreMetadata = new ProjectRestoreMetadata(); spec1.RestoreMetadata.ProjectUniqueName = "project1"; spec1.RestoreMetadata.ProjectName = "project1"; spec1.RestoreMetadata.ProjectStyle = ProjectStyle.PackageReference; spec1.RestoreMetadata.OriginalTargetFrameworks.Add("net45"); var spec2 = new PackageSpec(frameworks2); spec2.RestoreMetadata = new ProjectRestoreMetadata(); spec2.RestoreMetadata.ProjectUniqueName = "project2"; spec2.RestoreMetadata.ProjectName = "project2"; spec2.RestoreMetadata.ProjectStyle = ProjectStyle.PackageReference; spec2.RestoreMetadata.OriginalTargetFrameworks.Add("net45"); var specs = new[] { spec1, spec2 }; using (var workingDir = TestDirectory.Create()) { var packagesDir = new DirectoryInfo(Path.Combine(workingDir, "globalPackages")); var packageSource = new DirectoryInfo(Path.Combine(workingDir, "packageSource")); var project1 = new DirectoryInfo(Path.Combine(workingDir, "projects", "project1")); var project2 = new DirectoryInfo(Path.Combine(workingDir, "projects", "project2")); packagesDir.Create(); packageSource.Create(); project1.Create(); project2.Create(); sources.Add(new PackageSource(packageSource.FullName)); var projPath1 = Path.Combine(project1.FullName, "project1.csproj"); var projPath2 = Path.Combine(project2.FullName, "project2.csproj"); File.WriteAllText(projPath1, string.Empty); File.WriteAllText(projPath2, string.Empty); spec1.RestoreMetadata.ProjectPath = projPath1; spec1.FilePath = projPath1; spec1.Name = "project1"; spec2.RestoreMetadata.ProjectPath = projPath2; spec2.FilePath = projPath1; spec2.Name = "project2"; var logger = new TestLogger(); var objPath1 = Path.Combine(project1.FullName, "obj"); var objPath2 = Path.Combine(project2.FullName, "obj"); spec1.RestoreMetadata.OutputPath = objPath1; spec2.RestoreMetadata.OutputPath = objPath2; spec1.RestoreMetadata.OriginalTargetFrameworks.Add("net45"); spec2.RestoreMetadata.OriginalTargetFrameworks.Add("net45"); var lockPath1 = Path.Combine(objPath1, "project.assets.json"); var lockPath2 = Path.Combine(objPath2, "project.assets.json"); // Link projects spec1.TargetFrameworks.Single().Dependencies.Add(new LibraryDependency() { LibraryRange = new LibraryRange() { Name = "project2", TypeConstraint = LibraryDependencyTarget.ExternalProject } }); spec1.RestoreMetadata.TargetFrameworks.Add(new ProjectRestoreMetadataFrameworkInfo(NuGetFramework.Parse("net45"))); spec1.RestoreMetadata.TargetFrameworks .Single() .ProjectReferences .Add(new ProjectRestoreReference() { ProjectPath = projPath2, ProjectUniqueName = "project2" }); // Create dg file var dgFile = new DependencyGraphSpec(); foreach (var spec in specs) { dgFile.AddRestore(spec.RestoreMetadata.ProjectName); dgFile.AddProject(spec); } var dgPath = Path.Combine(workingDir, "input.dg"); dgFile.Save(dgPath); var sourceRepos = sources.Select(source => Repository.Factory.GetCoreV3(source.Source)).ToList(); var providerCache = new RestoreCommandProvidersCache(); using (var cacheContext = new SourceCacheContext()) { var restoreContext = new RestoreArgs() { CacheContext = cacheContext, DisableParallel = true, GlobalPackagesFolder = packagesDir.FullName, Sources = new List <string>() { packageSource.FullName }, Inputs = new List <string>() { dgPath }, Log = logger, CachingSourceProvider = new CachingSourceProvider(new TestPackageSourceProvider(sources)), RequestProviders = new List <IRestoreRequestProvider>() { new DependencyGraphFileRequestProvider(providerCache) } }; // Act var summaries = await RestoreRunner.Run(restoreContext); var success = summaries.All(s => s.Success); var lockFormat = new LockFileFormat(); var lockFile1 = lockFormat.Read(lockPath1); var project2Lib = lockFile1.Libraries.First(); // Assert Assert.True(success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); Assert.True(File.Exists(lockPath1), lockPath1); Assert.True(File.Exists(lockPath2), lockPath2); Assert.Equal("project2", project2Lib.Name); } } }
private static async Task <RestoreResultPair> PreviewAddPackageReferenceAsync(PackageReferenceArgs packageReferenceArgs, DependencyGraphSpec dgSpec) { // Set user agent and connection settings. XPlatUtility.ConfigureProtocol(); var providerCache = new RestoreCommandProvidersCache(); using (var cacheContext = new SourceCacheContext()) { cacheContext.NoCache = false; cacheContext.IgnoreFailedSources = false; // Pre-loaded request provider containing the graph file var providers = new List <IPreLoadedRestoreRequestProvider> { new DependencyGraphSpecRequestProvider(providerCache, dgSpec) }; var restoreContext = new RestoreArgs() { CacheContext = cacheContext, LockFileVersion = LockFileFormat.Version, Log = packageReferenceArgs.Logger, MachineWideSettings = new XPlatMachineWideSetting(), GlobalPackagesFolder = packageReferenceArgs.PackageDirectory, PreLoadedRequestProviders = providers, Sources = packageReferenceArgs.Sources?.ToList() }; // Generate Restore Requests. There will always be 1 request here since we are restoring for 1 project. var restoreRequests = await RestoreRunner.GetRequests(restoreContext); //Setup the Credential Service DefaultCredentialServiceUtility.SetupDefaultCredentialService(restoreContext.Log, !packageReferenceArgs.Interactive); // Run restore without commit. This will always return 1 Result pair since we are restoring for 1 request. var restoreResult = await RestoreRunner.RunWithoutCommit(restoreRequests, restoreContext); return(restoreResult.Single()); } }
public async Task ContentFilesMSBuild_VerifyConditionForFallbackContentItemGroup(string files, string expected) { // Arrange var logger = new TestLogger(); using (var cacheContext = new SourceCacheContext()) using (var pathContext = new SimpleTestPathContext()) { var tfi = new List <TargetFrameworkInformation> { new TargetFrameworkInformation() { FrameworkName = NuGetFramework.Parse("net462") } }; var spec = NETCoreRestoreTestUtility.GetProject(projectName: "projectA", framework: "net46"); spec.Dependencies.Add(new LibraryDependency() { LibraryRange = new LibraryRange("a", VersionRange.Parse("1.0.0"), LibraryDependencyTarget.Package) }); var project = NETCoreRestoreTestUtility.CreateProjectsFromSpecs(pathContext, spec).Single(); var packageA = new SimpleTestPackageContext("a"); packageA.AddFile("contentFiles/any/any/anyMarker.txt"); foreach (var file in files.Split('|')) { packageA.AddFile(file); } SimpleTestPackageUtility.CreatePackages(pathContext.PackageSource, packageA); // Create dg file var dgFile = new DependencyGraphSpec(); dgFile.AddProject(spec); dgFile.AddRestore(spec.RestoreMetadata.ProjectUniqueName); dgFile.Save(Path.Combine(pathContext.WorkingDirectory, "out.dg")); // Act var result = (await NETCoreRestoreTestUtility.RunRestore( pathContext, logger, new List <PackageSource>() { new PackageSource(pathContext.PackageSource) }, dgFile, cacheContext)).Single(); var props = XDocument.Load(project.PropsOutput); var itemGroups = props.Root.Elements(XName.Get("ItemGroup", "http://schemas.microsoft.com/developer/msbuild/2003")).ToArray(); var group = itemGroups.Single(e => e.ToString().Contains("anyMarker.txt")); // Assert Assert.True(result.Success, logger.ShowErrors()); Assert.Equal(expected.Trim(), group.Attribute(XName.Get("Condition")).Value.Trim()); } }
/// <summary> /// Restores a package by querying, downloading, and unzipping it without generating any other files (like project.assets.json). /// </summary> /// <param name="libraryIdentity">The <see cref="LibraryIdentity"/> of the package.</param> /// <param name="settings">The NuGet settings to use.</param> /// <param name="logger">An <see cref="ILogger"/> to use for logging.</param> /// <returns></returns> public static Task <IReadOnlyList <RestoreResultPair> > RunWithoutCommit(LibraryIdentity libraryIdentity, ISettings settings, ILogger logger) { using (var sourceCacheContext = new SourceCacheContext { IgnoreFailedSources = true, }) { var projectDirectory = Path.Combine(NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp), Guid.NewGuid().ToString("N")); var projectName = Guid.NewGuid().ToString("N"); var projectFullPath = Path.Combine(projectDirectory, $"{projectName}.proj"); // Iterate through TargetFrameworks to generate Lists required for packageSpec var frameworks = new List <TargetFrameworkInformation>(TargetFrameworks.Count); var originalTargetFrameworks = new List <string>(TargetFrameworks.Count); foreach (var tf in TargetFrameworks) { frameworks.Add(new TargetFrameworkInformation { FrameworkName = tf }); originalTargetFrameworks.Add(tf.ToString()); } // The package spec details what packages to restore var packageSpec = new PackageSpec(frameworks) { Dependencies = new List <LibraryDependency> { new LibraryDependency { LibraryRange = new LibraryRange( libraryIdentity.Name, new VersionRange( minVersion: libraryIdentity.Version, includeMinVersion: true, maxVersion: libraryIdentity.Version, includeMaxVersion: true), LibraryDependencyTarget.Package), SuppressParent = LibraryIncludeFlags.All, AutoReferenced = true, IncludeType = LibraryIncludeFlags.None, } }, RestoreMetadata = new ProjectRestoreMetadata { ProjectPath = projectFullPath, ProjectName = projectName, ProjectStyle = ProjectStyle.PackageReference, ProjectUniqueName = projectFullPath, OutputPath = projectDirectory, OriginalTargetFrameworks = originalTargetFrameworks, ConfigFilePaths = settings.GetConfigFilePaths(), PackagesPath = SettingsUtility.GetGlobalPackagesFolder(settings), Sources = SettingsUtility.GetEnabledSources(settings).AsList(), FallbackFolders = SettingsUtility.GetFallbackPackageFolders(settings).ToList() }, FilePath = projectFullPath, Name = projectName, }; var dependencyGraphSpec = new DependencyGraphSpec(); dependencyGraphSpec.AddProject(packageSpec); dependencyGraphSpec.AddRestore(packageSpec.RestoreMetadata.ProjectUniqueName); IPreLoadedRestoreRequestProvider requestProvider = new DependencyGraphSpecRequestProvider(new RestoreCommandProvidersCache(), dependencyGraphSpec); var restoreArgs = new RestoreArgs { AllowNoOp = false, CacheContext = sourceCacheContext, #pragma warning disable CS0618 // Type or member is obsolete CachingSourceProvider = new CachingSourceProvider(new PackageSourceProvider(settings, enablePackageSourcesChangedEvent: false)), #pragma warning restore CS0618 // Type or member is obsolete Log = logger, }; // Create requests from the arguments var requests = requestProvider.CreateRequests(restoreArgs).Result; // Restore the package without generating extra files return(RestoreRunner.RunWithoutCommit(requests, restoreArgs)); } }
public void GetParents_WithMultiLevelGraph_WhenALeafIsDirty_ReturnsProjectsFromEveryLevelAsDirty() { var projectA = GetPackageSpec("A"); var projectB = GetPackageSpec("B"); var projectC = GetPackageSpec("C"); var projectD = GetPackageSpec("D"); var projectE = GetPackageSpec("E"); var projectF = GetPackageSpec("F"); var projectG = GetPackageSpec("G"); var projectH = GetPackageSpec("H"); var projectI = GetPackageSpec("I"); var projectJ = GetPackageSpec("J"); var projectK = GetPackageSpec("K"); var projectL = GetPackageSpec("L"); var projectM = GetPackageSpec("M"); // A => B & C projectA = projectA.WithTestProjectReference(projectB).WithTestProjectReference(projectC); // B => D projectB = projectB.WithTestProjectReference(projectD); // D => F projectD = projectD.WithTestProjectReference(projectF); // C => E projectC = projectC.WithTestProjectReference(projectE); // G => D projectG = projectG.WithTestProjectReference(projectD); // H => C projectH = projectH.WithTestProjectReference(projectC); // I => F projectI = projectI.WithTestProjectReference(projectF); // H => I projectH = projectH.WithTestProjectReference(projectI); // K => L projectK = projectK.WithTestProjectReference(projectL); // J => K projectJ = projectJ.WithTestProjectReference(projectK); // H => J projectH = projectH.WithTestProjectReference(projectJ); // M => L projectM = projectM.WithTestProjectReference(projectL); var dgSpec = new DependencyGraphSpec(); dgSpec.AddProject(projectA); dgSpec.AddRestore(projectA.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectB); dgSpec.AddRestore(projectB.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectC); dgSpec.AddRestore(projectC.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectD); dgSpec.AddRestore(projectD.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectE); dgSpec.AddRestore(projectE.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectF); dgSpec.AddRestore(projectF.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectG); dgSpec.AddRestore(projectG.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectH); dgSpec.AddRestore(projectH.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectI); dgSpec.AddRestore(projectI.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectJ); dgSpec.AddRestore(projectJ.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectK); dgSpec.AddRestore(projectK.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectL); dgSpec.AddRestore(projectL.RestoreMetadata.ProjectUniqueName); dgSpec.AddProject(projectM); dgSpec.AddRestore(projectM.RestoreMetadata.ProjectUniqueName); var expected = GetUniqueNames(projectA, projectC, projectE, projectH, projectJ, projectK, projectL, projectM); var actual = SolutionUpToDateChecker.GetParents(GetUniqueNames(projectE, projectL), dgSpec); actual.Should().BeEquivalentTo(expected); }
public void Json_WhenDgSpecWasCreatedWithDefaultConstructor_ReturnsEmptyObject() { var dgSpec = new DependencyGraphSpec(); Assert.Empty(dgSpec.Json); }
public static async Task <(DependencyGraphSpec dgSpec, IReadOnlyList <IAssetsLogMessage> additionalMessages)> GetSolutionRestoreSpecAndAdditionalMessages( ISolutionManager solutionManager, DependencyGraphCacheContext context) { var dgSpec = new DependencyGraphSpec(); List <IAssetsLogMessage> allAdditionalMessages = null; var projects = (await solutionManager.GetNuGetProjectsAsync()).OfType <IDependencyGraphProject>().ToList(); var knownProjects = projects.Select(e => e.MSBuildProjectPath).ToHashSet(PathUtility.GetStringComparerBasedOnOS()); for (var i = 0; i < projects.Count; i++) { var(packageSpecs, projectAdditionalMessages) = await projects[i].GetPackageSpecsAndAdditionalMessagesAsync(context); if (projectAdditionalMessages != null && projectAdditionalMessages.Count > 0) { if (allAdditionalMessages == null) { allAdditionalMessages = new List <IAssetsLogMessage>(); } allAdditionalMessages.AddRange(projectAdditionalMessages); } foreach (var packageSpec in packageSpecs) { dgSpec.AddProject(packageSpec); if (packageSpec.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference || packageSpec.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson || packageSpec.RestoreMetadata.ProjectStyle == ProjectStyle.DotnetCliTool || packageSpec.RestoreMetadata.ProjectStyle == ProjectStyle.Standalone) // Don't add global tools to restore specs for solutions { dgSpec.AddRestore(packageSpec.RestoreMetadata.ProjectUniqueName); var projFileName = Path.GetFileName(packageSpec.RestoreMetadata.ProjectPath); var dgFileName = DependencyGraphSpec.GetDGSpecFileName(projFileName); var outputPath = packageSpec.RestoreMetadata.OutputPath; if (!string.IsNullOrEmpty(outputPath)) { for (int frameworkCount = 0; frameworkCount < packageSpec.RestoreMetadata.TargetFrameworks.Count; frameworkCount++) { for (var projectReferenceCount = 0; projectReferenceCount < packageSpec.RestoreMetadata.TargetFrameworks[frameworkCount].ProjectReferences.Count; projectReferenceCount++) { if (!knownProjects.Contains(packageSpec.RestoreMetadata.TargetFrameworks[frameworkCount].ProjectReferences[projectReferenceCount].ProjectPath)) { var persistedDGSpecPath = Path.Combine(outputPath, dgFileName); if (File.Exists(persistedDGSpecPath)) { var persistedDGSpec = DependencyGraphSpec.Load(persistedDGSpecPath); foreach (var dependentPackageSpec in persistedDGSpec.Projects.Where(e => !knownProjects.Contains(e.RestoreMetadata.ProjectPath))) { // Include all the missing projects from the closure. // Figuring out exactly what we need would be too and an overkill. That will happen later in the DependencyGraphSpecRequestProvider knownProjects.Add(dependentPackageSpec.RestoreMetadata.ProjectPath); dgSpec.AddProject(dependentPackageSpec); } } } } } } } } } // Return dg file return(dgSpec, allAdditionalMessages); }
public void AddProject_WhenDependencyVersionIsNull_CentralPackageVersionAppliesOnlyWhenAutoReferencedIsFalse() { // Arrange var dependencyFoo = new LibraryDependency( new LibraryRange("foo", versionRange: null, LibraryDependencyTarget.Package), LibraryDependencyType.Default, LibraryIncludeFlags.All, LibraryIncludeFlags.All, new List <Common.NuGetLogCode>(), autoReferenced: false, generatePathProperty: true, versionCentrallyManaged: false, LibraryDependencyReferenceType.Direct, aliases: null); var dependencyBar = new LibraryDependency( new LibraryRange("bar", VersionRange.Parse("3.0.0"), LibraryDependencyTarget.Package), LibraryDependencyType.Default, LibraryIncludeFlags.All, LibraryIncludeFlags.All, new List <Common.NuGetLogCode>(), autoReferenced: true, generatePathProperty: true, versionCentrallyManaged: false, LibraryDependencyReferenceType.Direct, aliases: null); var dependencyBoom = new LibraryDependency( new LibraryRange("boom", versionRange: null, LibraryDependencyTarget.Package), LibraryDependencyType.Default, LibraryIncludeFlags.All, LibraryIncludeFlags.All, new List <Common.NuGetLogCode>(), autoReferenced: true, generatePathProperty: true, versionCentrallyManaged: false, LibraryDependencyReferenceType.Direct, aliases: null); var centralVersionFoo = new CentralPackageVersion("foo", VersionRange.Parse("1.0.0")); var centralVersionBar = new CentralPackageVersion("bar", VersionRange.Parse("2.0.0")); var centralVersionBoom = new CentralPackageVersion("boom", VersionRange.Parse("4.0.0")); var tfi = CreateTargetFrameworkInformation( new List <LibraryDependency>() { dependencyFoo, dependencyBar, dependencyBoom }, new List <CentralPackageVersion>() { centralVersionFoo, centralVersionBar, centralVersionBoom }); // Act DependencyGraphSpec dependencyGraphSpec = CreateDependencyGraphSpecWithCentralDependencies(tfi); // Assert Assert.Equal(1, dependencyGraphSpec.Projects.Count); PackageSpec packSpec = dependencyGraphSpec.Projects[0]; IList <TargetFrameworkInformation> tfms = packSpec.TargetFrameworks; IList <LibraryDependency> dependencies = tfms[0].Dependencies; Assert.Equal(1, tfms.Count); Assert.Equal(3, dependencies.Count); Assert.Equal("[1.0.0, )", dependencies.Where(d => d.Name == "foo").First().LibraryRange.VersionRange.ToNormalizedString()); Assert.True(dependencies.Where(d => d.Name == "foo").First().VersionCentrallyManaged); Assert.Equal("[3.0.0, )", dependencies.Where(d => d.Name == "bar").First().LibraryRange.VersionRange.ToNormalizedString()); Assert.False(dependencies.Where(d => d.Name == "bar").First().VersionCentrallyManaged); Assert.Null(dependencies.Where(d => d.Name == "boom").First().LibraryRange.VersionRange); }
public async Task GetInstallActionsAsync_WithProjectReferenceProject_WhenUpdatingPackage_ReturnsCorrectActions() { const string projectName = "a"; string projectId = Guid.NewGuid().ToString(); var projectSystemCache = new ProjectSystemCache(); using (TestDirectory testDirectory = TestDirectory.Create()) { var packageV1 = new SimpleTestPackageContext(packageId: "b", version: "1.0.0"); var packageV2 = new SimpleTestPackageContext(packageV1.Id, version: "2.0.0"); string packageSourceDirectoryPath = Path.Combine(testDirectory, "packageSource"); await SimpleTestPackageUtility.CreateFolderFeedV3Async( packageSourceDirectoryPath, PackageSaveMode.Defaultv3, packageV1, packageV2); var packageSource = new PackageSource(packageSourceDirectoryPath); var packageSources = new List <PackageSource>() { packageSource }; Initialize(packageSources); string projectFullPath = Path.Combine(testDirectory.Path, $"{projectName}.csproj"); var unconfiguredProject = new Mock <UnconfiguredProject>(); var configuredProject = new Mock <ConfiguredProject>(); var projectServices = new Mock <ConfiguredProjectServices>(); var packageReferencesService = new Mock <IPackageReferencesService>(); var result = new Mock <IUnresolvedPackageReference>(); unconfiguredProject.Setup(x => x.GetSuggestedConfiguredProjectAsync()) .ReturnsAsync(configuredProject.Object); configuredProject.SetupGet(x => x.Services) .Returns(projectServices.Object); projectServices.SetupGet(x => x.PackageReferences) .Returns(packageReferencesService.Object); packageReferencesService.Setup(x => x.AddAsync(It.IsNotNull <string>(), It.IsNotNull <string>())) .ReturnsAsync(new AddReferenceResult <IUnresolvedPackageReference>(result.Object, added: true)); var nuGetProjectServices = new Mock <INuGetProjectServices>(); nuGetProjectServices.SetupGet(x => x.ScriptService) .Returns(Mock.Of <IProjectScriptHostService>()); var project = new CpsPackageReferenceProject( projectName: projectName, projectUniqueName: projectFullPath, projectFullPath: projectFullPath, projectSystemCache, unconfiguredProject.Object, nuGetProjectServices.Object, projectId); PackageSpec packageSpec = CreatePackageSpec( project.ProjectName, Path.Combine(testDirectory, "package.spec")); DependencyGraphSpec projectRestoreInfo = ProjectJsonTestHelpers.GetDGSpecFromPackageSpecs(packageSpec); projectRestoreInfo.AddProject(packageSpec); var projectNames = new ProjectNames( fullName: projectFullPath, uniqueName: projectFullPath, shortName: projectName, customUniqueName: projectName, projectId: projectId); projectSystemCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, Array.Empty <IAssetsLogMessage>()); _solutionManager.NuGetProjects.Add(project); string[] projectIds = new[] { projectId }; string[] packageSourceNames = new[] { packageSource.Name }; await PerformOperationAsync(async (projectManager) => { IReadOnlyList <ProjectAction> actions = await projectManager.GetInstallActionsAsync( projectIds, packageV1.Identity, VersionConstraints.None, includePrelease: true, DependencyBehavior.Lowest, packageSourceNames, CancellationToken.None); Assert.NotEmpty(actions); Assert.Equal(1, actions.Count); ProjectAction action = actions[0]; Assert.Equal(packageV1.Identity, action.PackageIdentity); Assert.Equal(NuGetProjectActionType.Install, action.ProjectActionType); Assert.Equal(projectId, action.ProjectId); Assert.Equal(1, action.ImplicitActions.Count); ImplicitProjectAction implicitAction = action.ImplicitActions[0]; Assert.Equal(packageV1.Identity, implicitAction.PackageIdentity); Assert.Equal(NuGetProjectActionType.Install, implicitAction.ProjectActionType); await projectManager.ExecuteActionsAsync(actions, CancellationToken.None); }); await PerformOperationAsync(async (projectManager) => { IReadOnlyList <ProjectAction> actions = await projectManager.GetInstallActionsAsync( projectIds, packageV2.Identity, VersionConstraints.None, includePrelease: true, DependencyBehavior.Lowest, packageSourceNames, CancellationToken.None); Assert.NotEmpty(actions); Assert.Equal(1, actions.Count); ProjectAction action = actions[0]; Assert.Equal(packageV2.Identity, action.PackageIdentity); Assert.Equal(NuGetProjectActionType.Install, action.ProjectActionType); Assert.Equal(projectId, action.ProjectId); Assert.Equal(2, action.ImplicitActions.Count); ImplicitProjectAction implicitAction = action.ImplicitActions[0]; Assert.Equal(packageV1.Identity, implicitAction.PackageIdentity); Assert.Equal(NuGetProjectActionType.Uninstall, implicitAction.ProjectActionType); implicitAction = action.ImplicitActions[1]; Assert.Equal(packageV2.Identity, implicitAction.PackageIdentity); Assert.Equal(NuGetProjectActionType.Install, implicitAction.ProjectActionType); }); } }
/// <summary> /// Convert MSBuild items to a DependencyGraphSpec. /// </summary> public static DependencyGraphSpec GetDependencySpec(IEnumerable <IMSBuildItem> items) { if (items == null) { throw new ArgumentNullException(nameof(items)); } // Unique names created by the MSBuild restore target are project paths, these // can be different on case-insensitive file systems for the same project file. // To workaround this unique names should be compared based on the OS. var uniqueNameComparer = PathUtility.GetStringComparerBasedOnOS(); var graphSpec = new DependencyGraphSpec(); var itemsById = new Dictionary <string, List <IMSBuildItem> >(uniqueNameComparer); var restoreSpecs = new HashSet <string>(uniqueNameComparer); var validForRestore = new HashSet <string>(uniqueNameComparer); var projectPathLookup = new Dictionary <string, string>(uniqueNameComparer); var toolItems = new List <IMSBuildItem>(); // Sort items and add restore specs foreach (var item in items) { var projectUniqueName = item.GetProperty("ProjectUniqueName"); if (item.IsType("restorespec")) { restoreSpecs.Add(projectUniqueName); } else if (!string.IsNullOrEmpty(projectUniqueName)) { List <IMSBuildItem> idItems; if (!itemsById.TryGetValue(projectUniqueName, out idItems)) { idItems = new List <IMSBuildItem>(1); itemsById.Add(projectUniqueName, idItems); } idItems.Add(item); } } // Add projects var validProjectSpecs = itemsById.Values.Select(GetPackageSpec).Where(e => e != null); foreach (var spec in validProjectSpecs) { // Keep track of all project path casings var uniqueName = spec.RestoreMetadata.ProjectUniqueName; if (uniqueName != null && !projectPathLookup.ContainsKey(uniqueName)) { projectPathLookup.Add(uniqueName, uniqueName); } var projectPath = spec.RestoreMetadata.ProjectPath; if (projectPath != null && !projectPathLookup.ContainsKey(projectPath)) { projectPathLookup.Add(projectPath, projectPath); } if (spec.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference || spec.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson || spec.RestoreMetadata.ProjectStyle == ProjectStyle.DotnetCliTool || spec.RestoreMetadata.ProjectStyle == ProjectStyle.Standalone || spec.RestoreMetadata.ProjectStyle == ProjectStyle.DotnetToolReference) { validForRestore.Add(spec.RestoreMetadata.ProjectUniqueName); } graphSpec.AddProject(spec); } // Fix project reference casings to match the original project on case insensitive file systems. NormalizePathCasings(projectPathLookup, graphSpec); // Remove references to projects that could not be read by restore. RemoveMissingProjects(graphSpec); // Add valid projects to restore section foreach (var projectUniqueName in restoreSpecs.Intersect(validForRestore)) { graphSpec.AddRestore(projectUniqueName); } return(graphSpec); }
public async Task RestoreBuildTargetsAndProps_VerifyRestoreChangeAsync() { // Arrange using (var cacheContext = new SourceCacheContext()) using (var pathContext = new SimpleTestPathContext()) { var logger = new TestLogger(); var sources = new List <PackageSource> { new PackageSource(pathContext.PackageSource) }; var spec = GetProject("projectA", "net462", "netstandard1.6"); spec.RestoreMetadata.CrossTargeting = true; spec.Dependencies.Add(new LibraryDependency() { LibraryRange = new LibraryRange("x", VersionRange.Parse("1.0.0"), LibraryDependencyTarget.Package) }); // Create fake projects, the real data is in the specs var projects = CreateProjectsFromSpecs(pathContext, spec); // Create dg file var dgFile = new DependencyGraphSpec(); dgFile.AddProject(spec); dgFile.AddRestore(spec.RestoreMetadata.ProjectUniqueName); dgFile.Save(Path.Combine(pathContext.WorkingDirectory, "out.dg")); var packageX = new SimpleTestPackageContext() { Id = "x", Version = "1.0.0" }; var packageY = new SimpleTestPackageContext() { Id = "y", Version = "1.0.0" }; packageX.AddFile("build/x.targets"); packageX.AddFile("build/x.props"); packageX.AddFile("contentFiles/any/any/_._"); packageY.AddFile("build/y.targets"); packageY.AddFile("build/y.props"); packageY.AddFile("contentFiles/any/any/_._"); await SimpleTestPackageUtility.CreatePackagesAsync(pathContext.PackageSource, packageX, packageY); var project = projects[0]; // First restore var summaries = await RunRestoreAsync(pathContext, logger, sources, dgFile, cacheContext); var success = summaries.All(s => s.Success); Assert.True(success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); // Modify spec spec.Dependencies.Add(new LibraryDependency() { LibraryRange = new LibraryRange("y", VersionRange.Parse("1.0.0"), LibraryDependencyTarget.Package) }); // Act summaries = await RunRestoreAsync(pathContext, logger, sources, dgFile, cacheContext); success = summaries.All(s => s.Success); Assert.True(success, "Failed: " + string.Join(Environment.NewLine, logger.Messages)); // Verify the file was rewritten Assert.Contains("y.targets", File.ReadAllText(project.TargetsOutput)); Assert.Contains("y.props", File.ReadAllText(project.PropsOutput)); } }