File: ListOperators\FindUnderPath.cs
Web Access
Project: ..\..\..\src\Tasks\Microsoft.Build.Tasks.csproj (Microsoft.Build.Tasks.Core)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
 
using Microsoft.NET.StringTools;
 
#nullable disable
 
namespace Microsoft.Build.Tasks
{
    /// <summary>
    /// Given a list of items, determine which are in the cone of the folder passed in and which aren't.
    /// </summary>
    public class FindUnderPath : TaskExtension
    {
        /// <summary>
        /// Filter based on whether items fall under this path or not.
        /// </summary>
        [Required]
        public ITaskItem Path { get; set; }
 
        /// <summary>
        /// Files to consider.
        /// </summary>
        public ITaskItem[] Files { get; set; } = Array.Empty<ITaskItem>();
 
        /// <summary>
        /// Set to true if the paths of the output items should be updated to be absolute
        /// </summary>
        public bool UpdateToAbsolutePaths { get; set; }
 
        /// <summary>
        /// Files that were inside of Path.
        /// </summary>
        [Output]
        public ITaskItem[] InPath { get; set; }
 
        /// <summary>
        /// Files that were outside of Path.
        /// </summary>
        [Output]
        public ITaskItem[] OutOfPath { get; set; }
 
        /// <summary>
        /// Execute the task.
        /// </summary>
        public override bool Execute()
        {
            var inPathList = new List<ITaskItem>();
            var outOfPathList = new List<ITaskItem>();
 
            string conePath;
 
            try
            {
                conePath =
                    Strings.WeakIntern(
                        System.IO.Path.GetFullPath(FileUtilities.FixFilePath(Path.ItemSpec)));
                conePath = FileUtilities.EnsureTrailingSlash(conePath);
            }
            catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
            {
                Log.LogErrorWithCodeFromResources(null, "", 0, 0, 0, 0,
                    "FindUnderPath.InvalidParameter", "Path", Path.ItemSpec, e.Message);
                return false;
            }
 
            int conePathLength = conePath.Length;
 
            Log.LogMessageFromResources(MessageImportance.Low, "FindUnderPath.ComparisonPath", Path.ItemSpec);
 
            foreach (ITaskItem item in Files)
            {
                string fullPath;
                try
                {
                    fullPath =
                        Strings.WeakIntern(
                            System.IO.Path.GetFullPath(FileUtilities.FixFilePath(item.ItemSpec)));
                }
                catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
                {
                    Log.LogErrorWithCodeFromResources(null, "", 0, 0, 0, 0,
                        "FindUnderPath.InvalidParameter", "Files", item.ItemSpec, e.Message);
                    return false;
                }
 
                // Compare the left side of both strings to see if they're equal.
                if (String.Compare(conePath, 0, fullPath, 0, conePathLength, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    // If we should use the absolute path, update the item contents
                    // Since ItemSpec, which fullPath comes from, is unescaped, re-escape when setting
                    // item.ItemSpec, since the setter for ItemSpec expects an escaped value.
                    if (UpdateToAbsolutePaths)
                    {
                        item.ItemSpec = EscapingUtilities.Escape(fullPath);
                    }
 
                    inPathList.Add(item);
                }
                else
                {
                    outOfPathList.Add(item);
                }
            }
 
            InPath = inPathList.ToArray();
            OutOfPath = outOfPathList.ToArray();
            return true;
        }
    }
}