@@ -21,6 +21,14 @@ internal static class ContentFileUtils
2121 {
2222 private const string ContentFilesFolderName = "contentFiles/" ;
2323
24+ /// <summary>
25+ /// Checks if a pattern contains glob wildcards (* or ?)
26+ /// </summary>
27+ private static bool ContainsGlobWildcards ( string pattern )
28+ {
29+ return pattern . IndexOfAny ( new [ ] { '*' , '?' } ) != - 1 ;
30+ }
31+
2432 /// <summary>
2533 /// Get all content groups that have the nearest TxM
2634 /// </summary>
@@ -107,13 +115,21 @@ internal static List<LockFileContentFile> GetContentFileGroup(
107115 // this is validated in the nuspec reader
108116 Debug . Assert ( filesEntry . Include != null , "invalid contentFiles entry" ) ;
109117
110- // Create a filesystem matcher for globbing patterns
111- var matcher = new Matcher ( StringComparison . OrdinalIgnoreCase ) ;
112- matcher . AddInclude ( filesEntry . Include ) ;
118+ // Optimize for the common case: exact file path without wildcards
119+ // When there are no wildcards and no exclude, use simple string comparison
120+ bool useSimpleMatch = ! ContainsGlobWildcards ( filesEntry . Include ) && filesEntry . Exclude == null ;
113121
114- if ( filesEntry . Exclude != null )
122+ Matcher ? matcher = null ;
123+ if ( ! useSimpleMatch )
115124 {
116- matcher . AddExclude ( filesEntry . Exclude ) ;
125+ // Create a filesystem matcher for globbing patterns
126+ matcher = new Matcher ( StringComparison . OrdinalIgnoreCase ) ;
127+ matcher . AddInclude ( filesEntry . Include ) ;
128+
129+ if ( filesEntry . Exclude != null )
130+ {
131+ matcher . AddExclude ( filesEntry . Exclude ) ;
132+ }
117133 }
118134
119135 // Check each file against the patterns
@@ -128,17 +144,27 @@ internal static List<LockFileContentFile> GetContentFileGroup(
128144 {
129145 var relativePath = file . Substring ( rootFolderPathLength , file . Length - rootFolderPathLength ) ;
130146
131- // Check if the nuspec group include/exclude patterns apply to the file
132- var globbingDirectory = new FileProviderGlobbingDirectory (
133- fileProvider : new SingleFileProvider ( relativePath ) ,
134- fileInfo : rootDirectory ,
135- parent : null ) ;
136-
137- // Currently Matcher only returns the file name not the full path, each file must be
138- // check individually.
139- var matchResults = matcher . Execute ( globbingDirectory ) ;
147+ bool isMatch ;
148+ if ( useSimpleMatch )
149+ {
150+ // Fast path: simple case-insensitive string comparison
151+ isMatch = string . Equals ( relativePath , filesEntry . Include , StringComparison . OrdinalIgnoreCase ) ;
152+ }
153+ else
154+ {
155+ // Check if the nuspec group include/exclude patterns apply to the file
156+ var globbingDirectory = new FileProviderGlobbingDirectory (
157+ fileProvider : new SingleFileProvider ( relativePath ) ,
158+ fileInfo : rootDirectory ,
159+ parent : null ) ;
160+
161+ // Currently Matcher only returns the file name not the full path, each file must be
162+ // check individually.
163+ var matchResults = matcher ! . Execute ( globbingDirectory ) ;
164+ isMatch = matchResults . HasMatches ;
165+ }
140166
141- if ( matchResults . HasMatches )
167+ if ( isMatch )
142168 {
143169 entries . Add ( filesEntry ) ;
144170 }
0 commit comments