public void XProjUtility_DependencyNotFound() { // Arrange using (var workingDir = TestFileSystemUtility.CreateRandomTestFolder()) { var json1 = @"{ ""dependencies"": { ""project2"": ""1.0.0"" } }, ""frameworks"": { ""net46"": {} } }"; var proj1Folder = Path.Combine(workingDir, "project1"); Directory.CreateDirectory(proj1Folder); var path1 = Path.Combine(proj1Folder, "project.json"); File.WriteAllText(path1, json1); var xproj1 = Path.Combine(proj1Folder, "project1.xproj"); File.WriteAllText(xproj1, string.Empty); // Act var references = XProjUtility.GetProjectReferences(xproj1); // Assert Assert.Equal(0, references.Count()); } }
public override bool Execute() { var filePath = ProjectFile.ToString(); var output = XProjUtility.GetProjectReferences(filePath); ProjectClosureOutput = output.Select(name => new TaskItem(name)).ToArray(); return(true); }
public void XProjUtility_DependencyTargetProject() { // Arrange using (var workingDir = TestFileSystemUtility.CreateRandomTestFolder()) { var json1 = @"{ ""dependencies"": { }, ""frameworks"": { ""net46"": { ""dependencies"": { ""project2"": { ""version"": ""1.0.0"", ""target"": ""project"" } } } } }"; var json2 = @"{ ""frameworks"": { ""net46"": {} } }"; var proj1Folder = Path.Combine(workingDir, "project1"); var proj2Folder = Path.Combine(workingDir, "project2"); Directory.CreateDirectory(proj1Folder); Directory.CreateDirectory(proj2Folder); var path1 = Path.Combine(proj1Folder, "project.json"); var path2 = Path.Combine(proj2Folder, "project.json"); File.WriteAllText(path1, json1); File.WriteAllText(path2, json2); var xproj1 = Path.Combine(proj1Folder, "project1.xproj"); var xproj2 = Path.Combine(proj2Folder, "project2.xproj"); File.WriteAllText(xproj1, string.Empty); File.WriteAllText(xproj2, string.Empty); // Act var references = XProjUtility.GetProjectReferences(xproj1); var reference = references.FirstOrDefault(); // Assert Assert.Equal(xproj2, reference); } }
private async Task <IEnumerable <RestoreTargetGraph> > ExecuteRestoreAsync(NuGetv3LocalRepository localRepository, RemoteWalkContext context, CancellationToken token) { if (_request.Project.TargetFrameworks.Count == 0) { _logger.LogError(string.Format(CultureInfo.CurrentCulture, Strings.Log_ProjectDoesNotSpecifyTargetFrameworks, _request.Project.Name, _request.Project.FilePath)); _success = false; return(Enumerable.Empty <RestoreTargetGraph>()); } _logger.LogMinimal(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, _request.Project.FilePath)); // External references var updatedExternalProjects = new List <ExternalProjectReference>(_request.ExternalProjects); if (_request.ExternalProjects.Count > 0) { // There should be at most one match in the external projects. var rootProjectMatches = _request.ExternalProjects.Where(proj => string.Equals( _request.Project.Name, proj.PackageSpecProjectName, StringComparison.OrdinalIgnoreCase)) .ToList(); if (rootProjectMatches.Count > 1) { throw new InvalidOperationException($"Ambiguous project name '{_request.Project.Name}'."); } var rootProject = rootProjectMatches.SingleOrDefault(); if (rootProject != null) { // Replace the project spec with the passed in package spec, // for installs which are done in memory first this will be // different from the one on disk updatedExternalProjects.RemoveAll(project => project.UniqueName.Equals(rootProject.UniqueName, StringComparison.Ordinal)); var updatedReference = new ExternalProjectReference( rootProject.UniqueName, _request.Project, rootProject.MSBuildProjectPath, rootProject.ExternalProjectReferences); updatedExternalProjects.Add(updatedReference); // Determine if the targets and props files should be written out. context.IsMsBuildBased = XProjUtility.IsMSBuildBasedProject(rootProject.MSBuildProjectPath); } else { Debug.Fail("RestoreRequest.ExternaProjects contains references, but does not contain the top level references. Add the project we are restoring for."); throw new InvalidOperationException($"Missing external reference metadata for {_request.Project.Name}"); } } // Load repositories // the external project provider is specific to the current restore project var projectResolver = new PackageSpecResolver(_request.Project); context.ProjectLibraryProviders.Add( new PackageSpecReferenceDependencyProvider(projectResolver, updatedExternalProjects, _logger)); var remoteWalker = new RemoteDependencyWalker(context); var projectRange = new LibraryRange() { Name = _request.Project.Name, VersionRange = new VersionRange(_request.Project.Version), TypeConstraint = LibraryDependencyTarget.Project | LibraryDependencyTarget.ExternalProject }; // Resolve dependency graphs var allInstalledPackages = new HashSet <LibraryIdentity>(); var allGraphs = new List <RestoreTargetGraph>(); var runtimeIds = RequestRuntimeUtility.GetRestoreRuntimes(_request); var projectFrameworkRuntimePairs = CreateFrameworkRuntimePairs(_request.Project, runtimeIds); var projectRestoreRequest = new ProjectRestoreRequest( _request, _request.Project, _request.ExistingLockFile, _runtimeGraphCache, _runtimeGraphCacheByPackage); var projectRestoreCommand = new ProjectRestoreCommand(_logger, projectRestoreRequest); var result = await projectRestoreCommand.TryRestore( projectRange, projectFrameworkRuntimePairs, allInstalledPackages, localRepository, remoteWalker, context, writeToLockFile : true, token : token); var success = result.Item1; var runtimes = result.Item3; allGraphs.AddRange(result.Item2); _success = success; // Calculate compatibility profiles to check by merging those defined in the project with any from the command line foreach (var profile in _request.Project.RuntimeGraph.Supports) { CompatibilityProfile compatProfile; if (profile.Value.RestoreContexts.Any()) { // Just use the contexts from the project definition compatProfile = profile.Value; } else if (!runtimes.Supports.TryGetValue(profile.Value.Name, out compatProfile)) { // No definition of this profile found, so just continue to the next one _logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Strings.Log_UnknownCompatibilityProfile, profile.Key)); continue; } foreach (var pair in compatProfile.RestoreContexts) { _logger.LogDebug($" {profile.Value.Name} -> +{pair}"); _request.CompatibilityProfiles.Add(pair); } } // Walk additional runtime graphs for supports checks if (_success && _request.CompatibilityProfiles.Any()) { var compatibilityResult = await projectRestoreCommand.TryRestore(projectRange, _request.CompatibilityProfiles, allInstalledPackages, localRepository, remoteWalker, context, writeToLockFile : false, token : token); _success = compatibilityResult.Item1; // TryRestore may contain graphs that are already in allGraphs if the // supports section contains the same TxM as the project framework. var currentGraphs = new HashSet <KeyValuePair <NuGetFramework, string> >( allGraphs.Select(graph => new KeyValuePair <NuGetFramework, string>( graph.Framework, graph.RuntimeIdentifier)) ); foreach (var graph in compatibilityResult.Item2) { var key = new KeyValuePair <NuGetFramework, string>( graph.Framework, graph.RuntimeIdentifier); if (currentGraphs.Add(key)) { allGraphs.Add(graph); } } } return(allGraphs); }
/// <summary> /// Get only the direct dependencies from a project /// </summary> private DirectReferences GetDirectProjectReferences( EnvDTEProject project, string projectFileFullPath, ExternalProjectReferenceContext context, IVsEnumHierarchyItemsFactory itemsFactory, string rootProjectPath) { var logger = context.Logger; var cache = context.Cache; var result = new DirectReferences(); // Find a project.json in the project // This checks for files on disk to match how BuildIntegratedProjectSystem checks at creation time. // NuGet.exe also uses disk paths and not the project file. var projectName = Path.GetFileNameWithoutExtension(projectFileFullPath); var projectDirectory = Path.GetDirectoryName(projectFileFullPath); // Check for projectName.project.json and project.json string jsonConfigItem = ProjectJsonPathUtilities.GetProjectConfigPath( directoryPath: projectDirectory, projectName: projectName); var hasProjectJson = true; // Verify the file exists, otherwise clear it if (!File.Exists(jsonConfigItem)) { jsonConfigItem = null; hasProjectJson = false; } // Verify ReferenceOutputAssembly var excludedProjects = GetExcludedReferences(project, itemsFactory); var childReferences = new HashSet <string>(StringComparer.Ordinal); var hasMissingReferences = false; // find all references in the project foreach (var childReference in GetProjectReferences(project)) { try { var reference3 = childReference as Reference3; if (reference3 != null && !reference3.Resolved) { // Skip missing references and show a warning hasMissingReferences = true; continue; } // Skip missing references if (childReference.SourceProject != null) { if (EnvDTEProjectUtility.HasUnsupportedProjectCapability(childReference.SourceProject)) { // Skip this shared project continue; } var childName = EnvDTEProjectUtility.GetFullProjectPath(childReference.SourceProject); // Skip projects which have ReferenceOutputAssembly=false if (!string.IsNullOrEmpty(childName) && !excludedProjects.Contains(childName, StringComparer.OrdinalIgnoreCase)) { childReferences.Add(childName); result.ToProcess.Add(new DTEReference(childReference.SourceProject, childName)); } } else if (hasProjectJson) { // SDK references do not have a SourceProject or child references, // but they can contain project.json files, and should be part of the closure // SDKs are not projects, only the project.json name is checked here var possibleSdkPath = childReference.Path; if (!string.IsNullOrEmpty(possibleSdkPath) && !possibleSdkPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) && Directory.Exists(possibleSdkPath)) { var possibleProjectJson = Path.Combine( possibleSdkPath, ProjectJsonPathUtilities.ProjectConfigFileName); if (File.Exists(possibleProjectJson)) { childReferences.Add(possibleProjectJson); // add the sdk to the results here result.Processed.Add(new ExternalProjectReference( possibleProjectJson, childReference.Name, possibleProjectJson, msbuildProjectPath: null, projectReferences: Enumerable.Empty <string>())); } } } } catch (Exception ex) { // Exceptions are expected in some scenarios for native projects, // ignore them and show a warning hasMissingReferences = true; logger.LogDebug(ex.ToString()); Debug.Fail("Unable to find project closure: " + ex.ToString()); } } if (hasMissingReferences) { // Log a warning message once per project // This warning contains only the names of the root project and the project with the // broken reference. Attempting to display more details on the actual reference // that has the problem may lead to another exception being thrown. var warning = string.Format( CultureInfo.CurrentCulture, Strings.Warning_ErrorDuringProjectClosureWalk, projectName, rootProjectPath); logger.LogWarning(warning); } // For the xproj -> xproj -> csproj scenario find all xproj-> xproj references. if (projectFileFullPath.EndsWith(XProjUtility.XProjExtension, StringComparison.OrdinalIgnoreCase)) { // All xproj paths, these are already checked for project.json var xprojFiles = XProjUtility.GetProjectReferences(projectFileFullPath); if (xprojFiles.Count > 0) { var pathToProject = GetPathToDTEProjectLookup(project); foreach (var xProjPath in xprojFiles) { // Only add projects that we can find in the solution, otherwise they will // end up causing failures. If this is an actual failure the resolver will // fail when resolving the dependency from project.json Project xProjDTE; if (pathToProject.TryGetValue(xProjPath, out xProjDTE)) { var xProjFullPath = EnvDTEProjectUtility.GetFullProjectPath(xProjDTE); if (!string.IsNullOrEmpty(xProjFullPath)) { childReferences.Add(xProjFullPath); // Continue walking this project if it has not been walked already result.ToProcess.Add(new DTEReference(xProjDTE, xProjFullPath)); } } } } } // Only set a package spec project name if a package spec exists var packageSpecProjectName = jsonConfigItem == null ? null : projectName; // Add the parent project to the results result.Processed.Add(new ExternalProjectReference( projectFileFullPath, packageSpecProjectName, jsonConfigItem, projectFileFullPath, childReferences)); return(result); }