File: GetRestoreSolutionProjectsTask.cs
Web Access
Project: src\src\nuget-client\src\NuGet.Core\NuGet.Build.Tasks\NuGet.Build.Tasks.csproj (NuGet.Build.Tasks)
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable disable

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace NuGet.Build.Tasks
{
    /// <summary>
    /// Convert .metaproj paths to project paths.
    /// </summary>
    public class GetRestoreSolutionProjectsTask : Microsoft.Build.Utilities.Task
    {
        private const string MetaProjExtension = ".metaproj";

        /// <summary>
        /// Solution project references.
        /// </summary>
        [Required]
        public ITaskItem[] ProjectReferences { get; set; }

        /// <summary>
        /// Root path used for resolving the absolute project paths.
        /// </summary>
        [Required]
        public string SolutionFilePath { get; set; }

        /// <summary>
        /// Output items
        /// </summary>
        [Output]
        public ITaskItem[] OutputProjectReferences { get; set; }

        public override bool Execute()
        {
            var entries = new List<ITaskItem>();
            var parentDirectory = Path.GetDirectoryName(SolutionFilePath);

            foreach (var project in ProjectReferences)
            {
                if (string.IsNullOrEmpty(project.ItemSpec))
                {
                    continue;
                }

                var projectPath = Path.GetFullPath(Path.Combine(parentDirectory, project.ItemSpec));

                // Check for the metaproj extension, this is auto generated by solutions instead of 
                // the actual project path when build order is set. For the purpose of restore 
                // the order is not important so we remove the extension to get the real project path.
                if (projectPath.EndsWith(MetaProjExtension, StringComparison.OrdinalIgnoreCase))
                {
                    // Remove .metaproj from the path.
                    projectPath = projectPath.Substring(0, projectPath.Length - MetaProjExtension.Length);
                }

                // Clone items using the modified path
                var newEntry = new TaskItem(projectPath, project.CloneCustomMetadata());
                entries.Add(newEntry);
            }

            OutputProjectReferences = entries.ToArray();

            return true;
        }
    }
}