Пример #1
0
        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());
            }
        }
Пример #2
0
        public override bool Execute()
        {
            var filePath = ProjectFile.ToString();
            var output   = XProjUtility.GetProjectReferences(filePath);

            ProjectClosureOutput = output.Select(name => new TaskItem(name)).ToArray();

            return(true);
        }
Пример #3
0
        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);
        }