File: MakeDir.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 System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
 
#nullable disable
 
namespace Microsoft.Build.Tasks
{
    /// <summary>
    /// A task that creates a directory
    /// </summary>
    public class MakeDir : TaskExtension, IIncrementalTask
    {
        [Required]
        public ITaskItem[] Directories
        {
            get
            {
                ErrorUtilities.VerifyThrowArgumentNull(_directories, nameof(Directories));
                return _directories;
            }
 
            set => _directories = value;
        }
 
        [Output]
        public ITaskItem[] DirectoriesCreated { get; private set; }
 
        public bool FailIfNotIncremental { get; set; }
 
        private ITaskItem[] _directories;
 
        #region ITask Members
 
        /// <summary>
        /// Executes the MakeDir task. Create the directory.
        /// </summary>
        public override bool Execute()
        {
            var items = new List<ITaskItem>();
            var directoriesSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
 
            foreach (ITaskItem directory in Directories)
            {
                // Sometimes people pass in an item transform like @(myitem->'%(RelativeDir)') in order
                // to create a bunch of directories for a set of items.  But if the item
                // is in the current project directory, %(RelativeDir) evaluates to empty-string.  So,
                // here we check for that case.
                if (directory.ItemSpec.Length > 0)
                {
                    try
                    {
                        // For speed, eliminate duplicates caused by poor targets authoring
                        if (!directoriesSet.Contains(directory.ItemSpec))
                        {
                            // Only log a message if we actually need to create the folder
                            if (!FileUtilities.DirectoryExistsNoThrow(directory.ItemSpec))
                            {
                                if (FailIfNotIncremental)
                                {
                                    Log.LogErrorFromResources("MakeDir.Comment", directory.ItemSpec);
                                }
                                else
                                {
                                    // Do not log a fake command line as well, as it's superfluous, and also potentially expensive
                                    Log.LogMessageFromResources(MessageImportance.Normal, "MakeDir.Comment", directory.ItemSpec);
 
                                    Directory.CreateDirectory(FileUtilities.FixFilePath(directory.ItemSpec));
                                }
                            }
 
                            items.Add(directory);
                        }
                    }
                    catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
                    {
                        Log.LogErrorWithCodeFromResources("MakeDir.Error", directory.ItemSpec, e.Message);
                    }
 
                    // Add even on failure to avoid reattempting
                    directoriesSet.Add(directory.ItemSpec);
                }
            }
 
            DirectoriesCreated = items.ToArray();
 
            return !Log.HasLoggedErrors;
        }
 
        #endregion
    }
}