예제 #1
0
        /// <summary>
        /// Used for the purposes of evaluating an item specification. Given a filespec that may include wildcard characters * and
        /// ?, we translate it into an actual list of files. If the input filespec doesn't contain any wildcard characters, and it
        /// doesn't appear to point to an actual file on disk, then we just give back the input string as an array of length one,
        /// assuming that it wasn't really intended to be a filename (as items are not required to necessarily represent files).
        /// Any wildcards passed in that are unescaped will be treated as real wildcards.
        /// The "include" of items passed back from the filesystem will be returned canonically escaped.
        /// The ordering of the list returned is deterministic (it is sorted).
        /// Will never throw IO exceptions: if there is no match, returns the input verbatim.
        /// </summary>
        /// <param name="directoryEscaped">The directory to evaluate, escaped.</param>
        /// <param name="filespecEscaped">The filespec to evaluate, escaped.</param>
        /// <param name="returnEscaped"><code>true</code> to return escaped specs.</param>
        /// <param name="excludeSpecsEscaped">The exclude specification, escaped.</param>
        /// <returns>Array of file paths.</returns>
        private static string[] GetFileList
        (
            string directoryEscaped,
            string filespecEscaped,
            bool returnEscaped,
            IEnumerable <string> excludeSpecsEscaped = null
        )
        {
            ErrorUtilities.VerifyThrowInternalLength(filespecEscaped, "filespecEscaped");

            if (excludeSpecsEscaped == null)
            {
                excludeSpecsEscaped = Enumerable.Empty <string>();
            }

            string[] fileList;

            if (FilespecHasWildcards(filespecEscaped))
            {
                // Unescape before handing it to the filesystem.
                var directoryUnescaped    = EscapingUtilities.UnescapeAll(directoryEscaped);
                var filespecUnescaped     = EscapingUtilities.UnescapeAll(filespecEscaped);
                var excludeSpecsUnescaped = excludeSpecsEscaped.Where(IsValidExclude).Select(EscapingUtilities.UnescapeAll).ToList();

                // Get the list of actual files which match the filespec.  Put
                // the list into a string array.  If the filespec started out
                // as a relative path, we will get back a bunch of relative paths.
                // If the filespec started out as an absolute path, we will get
                // back a bunch of absolute paths.
                fileList = FileMatcher.GetFiles(directoryUnescaped, filespecUnescaped, excludeSpecsUnescaped);

                ErrorUtilities.VerifyThrow(fileList != null, "We must have a list of files here, even if it's empty.");

                // Before actually returning the file list, we sort them alphabetically.  This
                // provides a certain amount of extra determinism and reproducability.  That is,
                // we're sure that the build will behave in exactly the same way every time,
                // and on every machine.
                Array.Sort(fileList, StringComparer.OrdinalIgnoreCase);

                if (returnEscaped)
                {
                    // We must now go back and make sure all special characters are escaped because we always
                    // store data in the engine in escaped form so it doesn't interfere with our parsing.
                    // Note that this means that characters that were not escaped in the original filespec
                    // may now be escaped, but that's not easy to avoid.
                    for (int i = 0; i < fileList.Length; i++)
                    {
                        fileList[i] = EscapingUtilities.Escape(fileList[i]);
                    }
                }
            }
            else
            {
                // Just return the original string.
                fileList = new string[] { returnEscaped?filespecEscaped : EscapingUtilities.UnescapeAll(filespecEscaped) };
            }

            return(fileList);
        }
예제 #2
0
        /// <summary>
        /// Expand wildcards in the item list.
        /// </summary>
        /// <param name="expand"></param>
        /// <returns>Array of items expanded</returns>
        public static ITaskItem[] ExpandWildcards(ITaskItem[] expand)
        {
            if (expand == null)
            {
                return(null);
            }
            else
            {
                List <ITaskItem> expanded = new List <ITaskItem>(expand.Length);
                foreach (ITaskItem i in expand)
                {
                    if (FileMatcher.HasWildcards(i.ItemSpec))
                    {
                        string[] files;
                        string   directoryName = Path.GetDirectoryName(i.ItemSpec);
                        string   searchPattern = Path.GetFileName(i.ItemSpec);

                        // Very often with TLog files we're talking about
                        // a directory and a simply wildcarded filename
                        // Optimize for that case here.
                        if (!FileMatcher.HasWildcards(directoryName) && Directory.Exists(directoryName))
                        {
                            files = Directory.GetFiles(directoryName, searchPattern);
                        }
                        else
                        {
                            files = FileMatcher.GetFiles(null, i.ItemSpec);
                        }

                        foreach (string file in files)
                        {
                            TaskItem newItem = new TaskItem((ITaskItem)i);
                            newItem.ItemSpec = file;
                            expanded.Add(newItem);
                        }
                    }
                    else
                    {
                        expanded.Add(i);
                    }
                }
                return(expanded.ToArray());
            }
        }
예제 #3
0
        /// <summary>
        /// Expand wildcards in the item list.
        /// </summary>
        /// <param name="expand"></param>
        /// <returns></returns>
        private static ITaskItem[] ExpandWildcards(ITaskItem[] expand)
        {
            if (expand == null)
            {
                return(null);
            }
            else
            {
                ArrayList expanded = new ArrayList();
                foreach (ITaskItem i in expand)
                {
                    if (FileMatcher.HasWildcards(i.ItemSpec))
                    {
                        string[] files = FileMatcher.GetFiles(null /* use current directory */, i.ItemSpec);
                        foreach (string file in files)
                        {
                            TaskItem newItem = new TaskItem((ITaskItem)i);
                            newItem.ItemSpec = file;

                            // Compute the RecursiveDir portion.
                            FileMatcher.Result match = FileMatcher.FileMatch(i.ItemSpec, file);
                            if (match.isLegalFileSpec && match.isMatch)
                            {
                                if (match.wildcardDirectoryPart != null && match.wildcardDirectoryPart.Length > 0)
                                {
                                    newItem.SetMetadata(FileUtilities.ItemSpecModifiers.RecursiveDir, match.wildcardDirectoryPart);
                                }
                            }

                            expanded.Add(newItem);
                        }
                    }
                    else
                    {
                        expanded.Add(i);
                    }
                }
                return((ITaskItem[])expanded.ToArray(typeof(ITaskItem)));
            }
        }
        public static ITaskItem[] ExpandWildcards(ITaskItem[] expand)
        {
            if (expand == null)
            {
                return(null);
            }
            List <ITaskItem> list = new List <ITaskItem>(expand.Length);

            foreach (ITaskItem item in expand)
            {
                if (FileMatcher.HasWildcards(item.ItemSpec))
                {
                    string[] files;
                    string   directoryName = Path.GetDirectoryName(item.ItemSpec);
                    string   fileName      = Path.GetFileName(item.ItemSpec);
                    if (!FileMatcher.HasWildcards(directoryName) && Directory.Exists(directoryName))
                    {
                        files = Directory.GetFiles(directoryName, fileName);
                    }
                    else
                    {
                        files = FileMatcher.GetFiles(null, item.ItemSpec);
                    }
                    foreach (string str3 in files)
                    {
                        TaskItem item2 = new TaskItem(item)
                        {
                            ItemSpec = str3
                        };
                        list.Add(item2);
                    }
                }
                else
                {
                    list.Add(item);
                }
            }
            return(list.ToArray());
        }
예제 #5
0
        private static string[] GetFileList
        (
            string directoryEscaped,
            string filespecEscaped,
            bool returnEscaped,
            bool forceEvaluateWildCards,
            IEnumerable <string> excludeSpecsEscaped,
            FileMatcher fileMatcher,
            object loggingMechanism                    = null,
            IElementLocation includeLocation           = null,
            IElementLocation excludeLocation           = null,
            IElementLocation importLocation            = null,
            BuildEventContext buildEventContext        = null,
            string buildEventFileInfoFullPath          = null,
            bool disableExcludeDriveEnumerationWarning = false
        )
        {
            ErrorUtilities.VerifyThrowInternalLength(filespecEscaped, nameof(filespecEscaped));

            string[] fileList;

            // Used to properly detect and log drive enumerating wildcards when applicable.
            FileMatcher.SearchAction action = FileMatcher.SearchAction.None;
            string excludeFileSpec          = string.Empty;

            if (!FilespecHasWildcards(filespecEscaped) ||
                FilespecMatchesLazyWildcard(filespecEscaped, forceEvaluateWildCards))
            {
                // Just return the original string.
                fileList = new string[] { returnEscaped?filespecEscaped : EscapingUtilities.UnescapeAll(filespecEscaped) };
            }
            else
            {
                if (Traits.Instance.LogExpandedWildcards)
                {
                    ErrorUtilities.DebugTraceMessage("Expanding wildcard for file spec {0}", filespecEscaped);
                }

                // Unescape before handing it to the filesystem.
                var directoryUnescaped    = EscapingUtilities.UnescapeAll(directoryEscaped);
                var filespecUnescaped     = EscapingUtilities.UnescapeAll(filespecEscaped);
                var excludeSpecsUnescaped = excludeSpecsEscaped?.Where(IsValidExclude).Select(i => EscapingUtilities.UnescapeAll(i)).ToList();

                // Get the list of actual files which match the filespec.  Put
                // the list into a string array.  If the filespec started out
                // as a relative path, we will get back a bunch of relative paths.
                // If the filespec started out as an absolute path, we will get
                // back a bunch of absolute paths. Also retrieves the search action
                // and relevant Exclude filespec for drive enumerating wildcard detection.
                (fileList, action, excludeFileSpec) = fileMatcher.GetFiles(directoryUnescaped, filespecUnescaped, excludeSpecsUnescaped);

                // Determines whether Exclude filespec or passed in file spec should be
                // used in drive enumeration warning or exception.
                bool   excludeFileSpecIsEmpty = string.IsNullOrWhiteSpace(excludeFileSpec);
                string fileSpec = excludeFileSpecIsEmpty ? filespecUnescaped : excludeFileSpec;

                switch (action)
                {
                case (FileMatcher.SearchAction.LogDriveEnumeratingWildcard):
                    switch (loggingMechanism)
                    {
                    // Logging mechanism received from ItemGroupIntrinsicTask.
                    case TargetLoggingContext targetLoggingContext:
                        LogDriveEnumerationWarningWithTargetLoggingContext(
                            targetLoggingContext,
                            includeLocation,
                            excludeFileSpecIsEmpty,
                            disableExcludeDriveEnumerationWarning,
                            fileSpec);

                        break;

                    // Logging mechanism received from Evaluator.
                    case ILoggingService loggingService:
                        LogDriveEnumerationWarningWithLoggingService(
                            loggingService,
                            buildEventContext,
                            buildEventFileInfoFullPath,
                            filespecUnescaped);

                        break;

                    // Logging mechanism received from Evaluator and LazyItemEvaluator.IncludeOperation.
                    case EvaluationLoggingContext evaluationLoggingContext:
                        LogDriveEnumerationWarningWithEvaluationLoggingContext(
                            evaluationLoggingContext,
                            importLocation,
                            excludeFileSpecIsEmpty,
                            filespecUnescaped,
                            fileSpec);

                        break;

                    default:
                        throw new InternalErrorException($"Logging type {loggingMechanism.GetType()} is not understood by {nameof(GetFileList)}.");
                    }

                    break;

                case (FileMatcher.SearchAction.FailOnDriveEnumeratingWildcard):
                    switch (loggingMechanism)
                    {
                    // Logging mechanism received from ItemGroupIntrinsicTask.
                    case TargetLoggingContext targetLoggingContext:
                        ThrowDriveEnumerationExceptionWithTargetLoggingContext(
                            includeLocation,
                            excludeLocation,
                            excludeFileSpecIsEmpty,
                            filespecUnescaped,
                            fileSpec);

                        break;

                    // Logging mechanism received from Evaluator.
                    case ILoggingService loggingService:
                        ThrowDriveEnumerationExceptionWithLoggingService(includeLocation, filespecUnescaped);

                        break;

                    // Logging mechanism received from Evaluator and LazyItemEvaluator.IncludeOperation.
                    case EvaluationLoggingContext evaluationLoggingContext:
                        ThrowDriveEnumerationExceptionWithEvaluationLoggingContext(
                            importLocation,
                            includeLocation,
                            excludeLocation,
                            filespecUnescaped,
                            fileSpec,
                            excludeFileSpecIsEmpty);

                        break;

                    default:
                        throw new InternalErrorException($"Logging type {loggingMechanism.GetType()} is not understood by {nameof(GetFileList)}.");
                    }

                    break;

                default: break;
                }

                ErrorUtilities.VerifyThrow(fileList != null, "We must have a list of files here, even if it's empty.");

                // Before actually returning the file list, we sort them alphabetically.  This
                // provides a certain amount of extra determinism and reproducability.  That is,
                // we're sure that the build will behave in exactly the same way every time,
                // and on every machine.
                Array.Sort(fileList, StringComparer.OrdinalIgnoreCase);

                if (returnEscaped)
                {
                    // We must now go back and make sure all special characters are escaped because we always
                    // store data in the engine in escaped form so it doesn't interfere with our parsing.
                    // Note that this means that characters that were not escaped in the original filespec
                    // may now be escaped, but that's not easy to avoid.
                    for (int i = 0; i < fileList.Length; i++)
                    {
                        fileList[i] = EscapingUtilities.Escape(fileList[i]);
                    }
                }
            }

            return(fileList);
        }
예제 #6
0
        /// <summary>
        /// Used for the purposes of evaluating an item specification. Given a filespec that may include wildcard characters * and
        /// ?, we translate it into an actual list of files. If the input filespec doesn't contain any wildcard characters, and it
        /// doesn't appear to point to an actual file on disk, then we just give back the input string as an array of length one,
        /// assuming that it wasn't really intended to be a filename (as items are not required to necessarily represent files).
        /// </summary>
        /// <owner>RGoel</owner>
        /// <param name="filespec">The filespec to evaluate.</param>
        /// <returns>Array of file paths.</returns>
        internal static string[] GetFileListEscaped
        (
            string directory,
            string filespec
        )
        {
            ErrorUtilities.VerifyThrow(filespec.Length > 0, "Need a valid file-spec.");

            string[] fileList;

            bool containsEscapedWildcards = EscapingUtilities.ContainsEscapedWildcards(filespec);
            bool containsRealWildcards    = FileMatcher.HasWildcards(filespec);

            if (containsEscapedWildcards && containsRealWildcards)
            {
                // Umm, this makes no sense.  The item's Include has both escaped wildcards and
                // real wildcards.  What does he want us to do?  Go to the file system and find
                // files that literally have '*' in their filename?  Well, that's not going to
                // happen because '*' is an illegal character to have in a filename.

                // Just return the original string.
                fileList = new string[] { EscapingUtilities.Escape(filespec) };
            }
            else if (!containsEscapedWildcards && containsRealWildcards)
            {
                // Unescape before handing it to the filesystem.
                string filespecUnescaped = EscapingUtilities.UnescapeAll(filespec);

                // Get the list of actual files which match the filespec.  Put
                // the list into a string array.  If the filespec started out
                // as a relative path, we will get back a bunch of relative paths.
                // If the filespec started out as an absolute path, we will get
                // back a bunch of absolute paths.
                fileList = FileMatcher.GetFiles(directory, filespecUnescaped);

                ErrorUtilities.VerifyThrow(fileList != null, "We must have a list of files here, even if it's empty.");

                // Before actually returning the file list, we sort them alphabetically.  This
                // provides a certain amount of extra determinism and reproducability.  That is,
                // we're sure that the build will behave in exactly the same way every time,
                // and on every machine.
                Array.Sort(fileList);

                // We must now go back and make sure all special characters are escaped because we always
                // store data in the engine in escaped form so it doesn't screw up our parsing.
                // Note that this means that characters that were not escaped in the original filespec
                // may now be escaped, but that's not easy to avoid.
                for (int i = 0; i < fileList.Length; i++)
                {
                    fileList[i] = EscapingUtilities.Escape(fileList[i]);
                }
            }
            else
            {
                // No real wildcards means we just return the original string.  Don't even bother
                // escaping ... it should already be escaped appropriately since it came directly
                // from the project file or the OM host.
                fileList = new string[] { filespec };
            }

            return(fileList);
        }