示例#1
0
        private static (ITaskItem[] Element, FileMatcher.SearchAction Action, string FileSpec) ExpandWildcards(ITaskItem[] expand)
        {
            // Used to detect and log drive enumerating wildcard patterns.
            string[] files;
            FileMatcher.SearchAction action = FileMatcher.SearchAction.None;
            string itemSpec = string.Empty;

            if (expand == null)
            {
                return(null, action, itemSpec);
            }
            else
            {
                var expanded = new List <ITaskItem>();
                foreach (ITaskItem i in expand)
                {
                    if (FileMatcher.HasWildcards(i.ItemSpec))
                    {
                        (files, action, _) = FileMatcher.Default.GetFiles(null /* use current directory */, i.ItemSpec);
                        itemSpec           = i.ItemSpec;
                        if (action == FileMatcher.SearchAction.FailOnDriveEnumeratingWildcard)
                        {
                            return(expanded.ToArray(), action, itemSpec);
                        }

                        foreach (string file in files)
                        {
                            TaskItem newItem = new TaskItem(i)
                            {
                                ItemSpec = file
                            };

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

                            expanded.Add(newItem);
                        }
                    }
                    else
                    {
                        expanded.Add(i);
                    }
                }
                return(expanded.ToArray(), action, itemSpec);
            }
        }
示例#2
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);
        }