예제 #1
0
        // NOTE: Assumes auto-including items. Only used by the scripts metadata generator, which will be replaced with source generators in the future.
        public static IEnumerable <string> GetIncludeFiles(string projectPath, string itemType)
        {
            var excluded      = new List <string>();
            var includedFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs");

            var root = ProjectRootElement.Open(projectPath);

            Debug.Assert(root != null);

            foreach (var item in root.Items)
            {
                if (string.IsNullOrEmpty(item.Condition))
                {
                    continue;
                }

                if (item.ItemType != itemType)
                {
                    continue;
                }

                string normalizedExclude = item.Exclude.NormalizePath();

                var glob = MSBuildGlob.Parse(normalizedExclude);

                excluded.AddRange(includedFiles.Where(includedFile => glob.IsMatch(includedFile)));
            }

            includedFiles.RemoveAll(f => excluded.Contains(f));

            return(includedFiles);
        }
예제 #2
0
        public void GlobMatchingShouldWorkWithComplexRelativeLiterals()
        {
            var glob = MSBuildGlob.Parse("u/x", "../../u/x/d11/d21/../d22/../../d12/a.cs");

            Assert.True(glob.IsMatch(@"../x/d13/../../x/d12/d23/../a.cs"));
            Assert.False(glob.IsMatch(@"../x/d13/../x/d12/d23/../a.cs"));
        }
예제 #3
0
        public static ProjectItemElement FindItemOrNullAbs(this ProjectRootElement root, string itemType, string include, bool noCondition = false)
        {
            string normalizedInclude = Path.GetFullPath(include).NormalizePath();

            foreach (var itemGroup in root.ItemGroups)
            {
                if (noCondition && itemGroup.Condition.Length != 0)
                {
                    continue;
                }

                foreach (var item in itemGroup.Items)
                {
                    if (item.ItemType != itemType)
                    {
                        continue;
                    }

                    var glob = MSBuildGlob.Parse(Path.GetFullPath(item.Include).NormalizePath());

                    if (glob.IsMatch(normalizedInclude))
                    {
                        return(item);
                    }
                }
            }

            return(null);
        }
예제 #4
0
 public void GlobFromRootWithInvalidPathThrows()
 {
     foreach (var invalidPathChar in FileUtilities.InvalidPathChars)
     {
         Assert.Throws <ArgumentException>(() => MSBuildGlob.Parse(invalidPathChar.ToString(), "*"));
     }
 }
예제 #5
0
        public void MSBuildGlobVisitorShouldFindAllLeaves()
        {
            var g1 = MSBuildGlob.Parse("1*");
            var g2 = MSBuildGlob.Parse("2*");
            var g3 = MSBuildGlob.Parse("3*");
            var g4 = MSBuildGlob.Parse("4*");

            var expectedCollectedGlobs = new[]
            {
                g1,
                g2,
                g3,
                g4
            };

            var composite = new CompositeGlob(
                g1,
                g2,
                new CompositeGlob(
                    new MSBuildGlobWithGaps(g3, MSBuildGlob.Parse("x*")),
                    new CompositeGlob(
                        g4
                        )
                    )
                );

            var leafGlobs = composite.GetParsedGlobs().ToArray();

            Assert.Equal(4, leafGlobs.Length);

            foreach (var expectedGlob in expectedCollectedGlobs)
            {
                Assert.Contains(expectedGlob, leafGlobs);
            }
        }
예제 #6
0
        public void CreateShouldReturnSingleChildUnchanged()
        {
            var glob = MSBuildGlob.Parse("");

            IMSBuildGlob composite = CompositeGlob.Create(new[] { glob });

            Assert.Same(glob, composite);
        }
예제 #7
0
        public void GlobFromRelativeGlobRootNormalizesRootAgainstCurrentDirectory()
        {
            var globRoot = "a/b/c";
            var glob = MSBuildGlob.Parse(globRoot, "*");

            var expectedRoot = NormalizeRelativePathForGlobRepresentation(globRoot);
            Assert.Equal(expectedRoot, glob.TestOnlyGlobRoot);
        }
예제 #8
0
        public void GlobFromAbsoluteRootDoesNotChangeTheRoot()
        {
            var globRoot = NativeMethodsShared.IsWindows ? @"c:\a" : "/a";
            var glob = MSBuildGlob.Parse(globRoot, "*");

            var expectedRoot = Path.Combine(Directory.GetCurrentDirectory(), globRoot).WithTrailingSlash();
            Assert.Equal(expectedRoot, glob.TestOnlyGlobRoot);
        }
예제 #9
0
        public void GlobMatchingShouldTreatIllegalFileSpecAsLiteral()
        {
            var illegalSpec = "|...*";
            var glob        = MSBuildGlob.Parse(illegalSpec);

            Assert.False(glob.IsLegal);
            Assert.True(glob.IsMatch(illegalSpec));
        }
예제 #10
0
        public void GlobWithRelativeFixedDirectoryPartShouldMissmatchTheGlobRoot(string globRoot, string filespec, string expectedFixedDirectoryPart)
        {
            var glob = MSBuildGlob.Parse(globRoot, filespec);

            var expectedFixedDirectory = NormalizeRelativePathForGlobRepresentation(expectedFixedDirectoryPart);

            Assert.Equal(expectedFixedDirectory, glob.FixedDirectoryPart);
        }
예제 #11
0
        public void GlobParsingShouldDeduplicateRegexes()
        {
            var globRoot = NativeMethodsShared.IsWindows ? @"c:\a" : "/a";
            var fileSpec = $"b/**/*.cs";
            var glob1    = MSBuildGlob.Parse(globRoot, fileSpec);
            var glob2    = MSBuildGlob.Parse(globRoot, fileSpec);

            Assert.Same(glob1.TestOnlyRegex, glob2.TestOnlyRegex);
        }
예제 #12
0
        public void GlobIsNotUnescaped()
        {
            var glob = MSBuildGlob.Parse("%42/%42");

            Assert.True(glob.IsLegal);
            Assert.True(glob.FixedDirectoryPart.EndsWith("%42" + Path.DirectorySeparatorChar));
            Assert.Equal(string.Empty, glob.WildcardDirectoryPart);
            Assert.Equal("%42", glob.FilenamePart);
        }
예제 #13
0
        public void CreateShouldReturnNewCompositeWhenMultipleProvided()
        {
            var glob1 = MSBuildGlob.Parse("");
            var glob2 = MSBuildGlob.Parse("");

            IMSBuildGlob result = CompositeGlob.Create(new[] { glob1, glob2 });

            var composite = Assert.IsType <CompositeGlob>(result);

            Assert.Same(glob1, composite.Globs.First());
            Assert.Same(glob2, composite.Globs.Skip(1).First());
            Assert.Equal(2, composite.Globs.Count());
        }
예제 #14
0
        public void GlobMatchingShouldRespectTheRootOfTheGlob(string fileSpec, string stringToMatch, string globRoot, bool shouldMatch)
        {
            var glob = MSBuildGlob.Parse(globRoot, fileSpec);

            if (shouldMatch)
            {
                Assert.True(glob.IsMatch(stringToMatch));
            }
            else
            {
                Assert.False(glob.IsMatch(stringToMatch));
            }
        }
예제 #15
0
        public void GlobParsingShouldInitializePartialStateOnIllegalFileSpec()
        {
            var globRoot        = NativeMethodsShared.IsWindows ? @"c:\a" : "/a";
            var illegalFileSpec = $"b/.../**/*.cs";
            var glob            = MSBuildGlob.Parse(globRoot, illegalFileSpec);

            Assert.False(glob.IsLegal);
            Assert.Equal(false, glob._needsRecursion);
            Assert.Equal(illegalFileSpec, glob._fileSpec);

            Assert.Equal(globRoot.WithTrailingSlash(), glob._globRoot);

            Assert.Equal(string.Empty, glob.FixedDirectoryPart);
            Assert.Equal(string.Empty, glob.WildcardDirectoryPart);
            Assert.Equal(string.Empty, glob.FilenamePart);
        }
예제 #16
0
        public void GlobParsingShouldInitializeState()
        {
            var globRoot = NativeMethodsShared.IsWindows ? @"c:\a" : "/a";
            var fileSpec = $"b/**/*.cs";
            var glob     = MSBuildGlob.Parse(globRoot, fileSpec);

            var expectedFixedDirectory = Path.Combine(globRoot, "b").WithTrailingSlash();

            Assert.True(glob.IsLegal);
            Assert.Equal(true, glob._needsRecursion);
            Assert.Equal(fileSpec, glob._fileSpec);

            Assert.Equal(globRoot.WithTrailingSlash(), glob._globRoot);
            Assert.True(glob.FixedDirectoryPart.StartsWith(glob._globRoot));

            Assert.Equal(expectedFixedDirectory, glob.FixedDirectoryPart);
            Assert.Equal("**/", glob.WildcardDirectoryPart);
            Assert.Equal("*.cs", glob.FilenamePart);
        }
예제 #17
0
        public void GlobMatchShouldReturnFalseIfArgumentContainsInvalidPathOrFileCharacters()
        {
            var glob = MSBuildGlob.Parse("*");

            foreach (var invalidPathChar in FileUtilities.InvalidPathChars)
            {
                Assert.False(glob.IsMatch(invalidPathChar.ToString()));
            }

            foreach (var invalidFileChar in FileUtilities.InvalidFileNameChars)
            {
                if (invalidFileChar == '\\' || invalidFileChar == '/')
                {
                    continue;
                }

                Assert.False(glob.IsMatch(invalidFileChar.ToString()));
            }
        }
예제 #18
0
        public static void RenameItemInProjectChecked(string projectPath, string itemType, string oldInclude, string newInclude)
        {
            var dir  = Directory.GetParent(projectPath).FullName;
            var root = ProjectRootElement.Open(projectPath);

            Debug.Assert(root != null);

            if (root.AreDefaultCompileItemsEnabled())
            {
                // No need to add. It's already included automatically by the MSBuild Sdk.
                // This assumes the source file is inside the project directory and not manually excluded in the csproj
                return;
            }

            var normalizedOldInclude = oldInclude.NormalizePath();
            var normalizedNewInclude = newInclude.NormalizePath();

            var item = root.FindItemOrNullAbs(itemType, normalizedOldInclude);

            if (item == null)
            {
                return;
            }

            // Check if the found item include already matches the new path
            var glob = MSBuildGlob.Parse(item.Include);

            if (glob.IsMatch(normalizedNewInclude))
            {
                return;
            }

            // Otherwise, if the item include uses globbing it's better to add a new item instead of modifying
            if (!string.IsNullOrEmpty(glob.WildcardDirectoryPart) || glob.FilenamePart.Contains("*"))
            {
                root.AddItem(itemType, normalizedNewInclude.RelativeToPath(dir).Replace("/", "\\"));
                root.Save();
                return;
            }

            item.Include = normalizedNewInclude.RelativeToPath(dir).Replace("/", "\\");
            root.Save();
        }
예제 #19
0
        public static string[] GetIncludeFiles(string projectPath, string itemType)
        {
            var result        = new List <string>();
            var existingFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs");

            var root = ProjectRootElement.Open(projectPath);

            Debug.Assert(root != null);

            foreach (var itemGroup in root.ItemGroups)
            {
                if (itemGroup.Condition.Length != 0)
                {
                    continue;
                }

                foreach (var item in itemGroup.Items)
                {
                    if (item.ItemType != itemType)
                    {
                        continue;
                    }

                    string normalizedInclude = item.Include.NormalizePath();

                    var glob = MSBuildGlob.Parse(normalizedInclude);

                    // TODO Check somehow if path has no blob to avoid the following loop...

                    foreach (var existingFile in existingFiles)
                    {
                        if (glob.IsMatch(existingFile))
                        {
                            result.Add(existingFile);
                        }
                    }
                }
            }

            return(result.ToArray());
        }
예제 #20
0
        public void GlobMatchingBehaviourWhenInputIsASingleSlash()
        {
            var glob = MSBuildGlob.Parse("*");

            if (NativeMethodsShared.IsUnixLike)
            {
                // \ is an acceptable file character on Unix, * should match it
                Assert.True(glob.IsMatch("\\"));

                // / means root on Unix
                Assert.False(glob.IsMatch("/"));
            }
            else
            {
                // \ means partition root on Windows
                Assert.False(glob.IsMatch("\\"));

                // / also means partition root on Windows
                Assert.False(glob.IsMatch("/"));
            }
        }
예제 #21
0
        public void GlobMatchingIgnoresSlashOrientationAndRepetitions(string globRoot, string fileSpec, string stringToMatch,
            string fixedDirectoryPart, string wildcardDirectoryPart, string filenamePart)
        {
            var glob = MSBuildGlob.Parse(globRoot, fileSpec);

            Assert.True(glob.IsMatch(stringToMatch));

            MSBuildGlob.MatchInfoResult result = glob.MatchInfo(stringToMatch);
            Assert.True(result.IsMatch);

            string NormalizeSlashes(string path)
            {
                string normalizedPath = path.Replace(Path.DirectorySeparatorChar == '/' ? '\\' : '/', Path.DirectorySeparatorChar);
                return NativeMethodsShared.IsWindows ? normalizedPath.Replace("\\\\", "\\") : normalizedPath;
            }

            var rootedFixedDirectoryPart = Path.Combine(FileUtilities.NormalizePath(globRoot), fixedDirectoryPart);

            Assert.Equal(FileUtilities.GetFullPathNoThrow(rootedFixedDirectoryPart), result.FixedDirectoryPartMatchGroup);
            Assert.Equal(NormalizeSlashes(wildcardDirectoryPart), result.WildcardDirectoryPartMatchGroup);
            Assert.Equal(NormalizeSlashes(filenamePart), result.FilenamePartMatchGroup);
        }
예제 #22
0
        public void GlobRootEndsWithTrailingSlash(string globRoot)
        {
            var glob = MSBuildGlob.Parse(globRoot, "*");

            Assert.Equal(glob._globRoot.LastOrDefault(), Path.DirectorySeparatorChar);
        }
예제 #23
0
        public static string[] GetIncludeFiles(string projectPath, string itemType)
        {
            var result        = new List <string>();
            var existingFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs");

            var root = ProjectRootElement.Open(projectPath);

            Debug.Assert(root != null);

            if (root.AreDefaultCompileItemsEnabled())
            {
                var excluded = new List <string>();
                result.AddRange(existingFiles);

                foreach (var item in root.Items)
                {
                    if (string.IsNullOrEmpty(item.Condition))
                    {
                        continue;
                    }

                    if (item.ItemType != itemType)
                    {
                        continue;
                    }


                    string normalizedRemove = item.Remove.NormalizePath();

                    var glob = MSBuildGlob.Parse(normalizedRemove);

                    excluded.AddRange(result.Where(includedFile => glob.IsMatch(includedFile)));
                }

                result.RemoveAll(f => excluded.Contains(f));
            }

            foreach (var itemGroup in root.ItemGroups)
            {
                if (itemGroup.Condition.Length != 0)
                {
                    continue;
                }

                foreach (var item in itemGroup.Items)
                {
                    if (item.ItemType != itemType)
                    {
                        continue;
                    }

                    string normalizedInclude = item.Include.NormalizePath();

                    var glob = MSBuildGlob.Parse(normalizedInclude);

                    foreach (var existingFile in existingFiles)
                    {
                        if (glob.IsMatch(existingFile))
                        {
                            result.Add(existingFile);
                        }
                    }
                }
            }

            return(result.ToArray());
        }
예제 #24
0
 protected virtual IMSBuildGlob CreateMsBuildGlob()
 {
     return(MSBuildGlob.Parse(ProjectDirectory, EscapingUtilities.UnescapeAll(TextFragment)));
 }
예제 #25
0
파일: ItemSpec.cs 프로젝트: tkggand/msbuild
 protected virtual IMSBuildGlob CreateMsBuildGlob()
 {
     return MSBuildGlob.Parse(ProjectDirectory, TextFragment.Unescape());
 }
예제 #26
0
        public void GlobShouldMatchEmptyArgWhenGlobAcceptsEmptyString(string globRoot)
        {
            var glob = MSBuildGlob.Parse(globRoot, "*");

            Assert.True(glob.IsMatch(string.Empty));
        }
예제 #27
0
 public void GlobFromNullRootThrows()
 {
     Assert.Throws <ArgumentNullException>(() => MSBuildGlob.Parse(null, "*"));
 }
예제 #28
0
        public void GlobFromEmptyRootUsesCurrentDirectory()
        {
            var glob = MSBuildGlob.Parse(string.Empty, "*");

            Assert.Equal(Directory.GetCurrentDirectory().WithTrailingSlash(), glob._globRoot);
        }
예제 #29
0
        public void GlobMatchingIgnoresSlashOrientationAndRepetitions(string globRoot, string fileSpec, string stringToMatch)
        {
            var glob = MSBuildGlob.Parse(globRoot, fileSpec);

            Assert.True(glob.IsMatch(stringToMatch));
        }
예제 #30
0
        public void GlobShouldNotMatchEmptyArgWhenGlobDoesNotRepresentEmpty(string globRoot)
        {
            var glob = MSBuildGlob.Parse(globRoot, "*a*");

            Assert.False(glob.IsMatch(string.Empty));
        }