10
10
using NuGet . Common ;
11
11
using NuGet . Protocol ;
12
12
using NuGet . Protocol . Core . Types ;
13
- using NuGet . Versioning ;
14
13
using PackageManager . Logging ;
15
14
using PackageManager . Models ;
16
15
@@ -61,29 +60,11 @@ private SearchOptions EnsureOptions(SearchOptions options)
61
60
return options ;
62
61
}
63
62
64
- private Task < IEnumerable < IPackageSearchMetadata > > SearchAsync ( PackageSearchResource search , string searchText , SearchOptions options , CancellationToken cancellationToken )
65
- => search . SearchAsync ( searchText , new SearchFilter ( options . IsPrereleaseIncluded ) , options . PageIndex * options . PageSize , options . PageSize , nuGetLog , cancellationToken ) ;
66
-
67
63
public async Task < IEnumerable < IPackage > > SearchAsync ( IEnumerable < IPackageSource > packageSources , string searchText , SearchOptions options = default , CancellationToken cancellationToken = default )
68
64
{
69
- NuGetSearchTerm term = new NuGetSearchTerm ( ) ;
70
- term . Id . Add ( searchText ) ;
65
+ var ( feedTerm , localTerm ) = PrepareSearchTerms ( searchText ) ;
71
66
72
- queryTransformer . Transform ( term ) ;
73
- term . Id . Remove ( searchText ) ;
74
-
75
- NuGetSearchTerm lateTerm = null ;
76
- if ( term . IsEmpty ( ) )
77
- {
78
- term . Id . Add ( searchText ) ;
79
- }
80
- else
81
- {
82
- lateTerm = term . Clone ( ) ;
83
- lateTerm . Id . Add ( searchText ) ;
84
- }
85
-
86
- log . Debug ( $ "Searching - user text:'{ searchText } '; target query:'{ term } '.") ;
67
+ log . Debug ( $ "Searching - user text:'{ searchText } '; feed query:'{ feedTerm } '.") ;
87
68
88
69
options = EnsureOptions ( options ) ;
89
70
@@ -96,7 +77,6 @@ public async Task<IEnumerable<IPackage>> SearchAsync(IEnumerable<IPackageSource>
96
77
{
97
78
log . Debug ( $ "Loading page '{ options . PageIndex } '.") ;
98
79
99
- bool hasItems = false ;
100
80
foreach ( IPackageSource packageSource in sources )
101
81
{
102
82
log . Debug ( $ "Searching in '{ packageSource . Uri } '.") ;
@@ -106,60 +86,15 @@ public async Task<IEnumerable<IPackage>> SearchAsync(IEnumerable<IPackageSource>
106
86
if ( search == null )
107
87
{
108
88
log . Debug ( $ "Source skipped, because it doesn't provide '{ nameof ( PackageSearchResource ) } '.") ;
109
- continue ;
110
- }
111
-
112
- NuGetSearchTerm localTerm = null ;
113
- bool clearLateTerm = false ;
114
- if ( search is LocalPackageSearchResource )
115
- {
116
- // Searching a feed from folder.
117
- localTerm = term ;
118
- term = new NuGetSearchTerm ( ) ;
119
-
120
- if ( lateTerm == null )
121
- {
122
- lateTerm = localTerm ;
123
- clearLateTerm = true ;
124
- }
125
- }
126
-
127
- int sourceSearchPackageCount = 0 ;
128
- foreach ( IPackageSearchMetadata package in await SearchAsync ( search , term . ToString ( ) , options , cancellationToken ) )
129
- {
130
- log . Debug ( $ "Found '{ package . Identity } '.") ;
131
89
132
- hasItems = true ;
133
- if ( result . Count >= options . PageSize )
134
- break ;
135
-
136
- if ( lateTerm != null && ! lateTerm . IsMatched ( package ) )
137
- {
138
- log . Debug ( $ "Package skipped by late search term '{ lateTerm } '.") ;
139
- continue ;
140
- }
141
-
142
- await AddPackageAsync ( result , repository , package , options . IsPrereleaseIncluded , cancellationToken ) ;
143
- sourceSearchPackageCount ++ ;
90
+ sourcesToSkip . Add ( packageSource ) ;
91
+ continue ;
144
92
}
145
93
146
- // If package source reached end, skip it from next probing.
147
- if ( sourceSearchPackageCount < options . PageSize )
94
+ if ( ! await ApplyLocalResourceSearchAsync ( result , repository , search , feedTerm , localTerm , options , cancellationToken ) )
148
95
sourcesToSkip . Add ( packageSource ) ;
149
-
150
- if ( localTerm != null )
151
- {
152
- term = localTerm ;
153
- localTerm = null ;
154
-
155
- if ( clearLateTerm )
156
- lateTerm = null ;
157
- }
158
96
}
159
97
160
- if ( ! hasItems )
161
- break ;
162
-
163
98
options = new SearchOptions ( )
164
99
{
165
100
PageIndex = options . PageIndex + 1 ,
@@ -168,12 +103,99 @@ public async Task<IEnumerable<IPackage>> SearchAsync(IEnumerable<IPackageSource>
168
103
169
104
foreach ( IPackageSource source in sourcesToSkip )
170
105
sources . Remove ( source ) ;
106
+
107
+ if ( sources . Count == 0 )
108
+ break ;
171
109
}
172
110
173
111
log . Debug ( $ "Search completed. Found '{ result . Count } ' items.") ;
174
112
return result ;
175
113
}
176
114
115
+ /// <summary>
116
+ /// Prepares instance of terms for filtering in feed and in-app.
117
+ /// </summary>
118
+ /// <remarks>
119
+ /// localTerm should always have all search terms.
120
+ /// </remarks>
121
+ private ( NuGetSearchTerm feedTerm , NuGetSearchTerm localTerm ) PrepareSearchTerms ( string searchText )
122
+ {
123
+ NuGetSearchTerm feedTerm = new NuGetSearchTerm ( ) ;
124
+ feedTerm . Id . Add ( searchText ) ;
125
+
126
+ queryTransformer . Transform ( feedTerm ) ;
127
+ feedTerm . Id . Remove ( searchText ) ;
128
+
129
+ NuGetSearchTerm localTerm = null ;
130
+ if ( feedTerm . IsEmpty ( ) )
131
+ {
132
+ feedTerm . Id . Add ( searchText ) ;
133
+ }
134
+ else
135
+ {
136
+ localTerm = feedTerm . Clone ( ) ;
137
+ localTerm . Id . Add ( searchText ) ;
138
+ }
139
+
140
+ return ( feedTerm , localTerm ) ;
141
+ }
142
+
143
+ /// <summary>
144
+ /// Tries to apply special conditions for looking in local folder feed.
145
+ /// </summary>
146
+ /// <returns><c>true</c> if search reached the end of the feed; <c>false</c> otherwise.</returns>
147
+ private Task < bool > ApplyLocalResourceSearchAsync ( List < IPackage > result , SourceRepository repository , PackageSearchResource search , NuGetSearchTerm feedTerm , NuGetSearchTerm localTerm , SearchOptions options , CancellationToken cancellationToken )
148
+ {
149
+ if ( search is LocalPackageSearchResource )
150
+ {
151
+ // Searching a feed from folder. Look for all packages and then filter in-app.
152
+ if ( localTerm == null )
153
+ localTerm = feedTerm ;
154
+
155
+ feedTerm = new NuGetSearchTerm ( ) ;
156
+ }
157
+
158
+ return ApplySearchAsync ( result , repository , search , feedTerm , localTerm , options , cancellationToken ) ;
159
+ }
160
+
161
+ /// <summary>
162
+ /// Execute search on <paramref name="search"/>.
163
+ /// </summary>
164
+ /// <returns><c>true</c> if search reached the end of the feed; <c>false</c> otherwise.</returns>
165
+ private async Task < bool > ApplySearchAsync ( List < IPackage > result , SourceRepository repository , PackageSearchResource search , NuGetSearchTerm feedTerm , NuGetSearchTerm localTerm , SearchOptions options , CancellationToken cancellationToken )
166
+ {
167
+ if ( localTerm != null && options . PageSize == 1 )
168
+ options . PageSize = 10 ;
169
+
170
+ int sourceSearchPackageCount = 0 ;
171
+ foreach ( IPackageSearchMetadata package in await SearchAsync ( search , feedTerm . ToString ( ) , options , cancellationToken ) )
172
+ {
173
+ sourceSearchPackageCount ++ ;
174
+
175
+ log . Debug ( $ "Found '{ package . Identity } '.") ;
176
+
177
+ if ( result . Count >= options . PageSize )
178
+ break ;
179
+
180
+ if ( localTerm != null && ! localTerm . IsMatched ( package ) )
181
+ {
182
+ log . Debug ( $ "Package skipped by late search term '{ localTerm } '.") ;
183
+ continue ;
184
+ }
185
+
186
+ await AddPackageAsync ( result , repository , package , options . IsPrereleaseIncluded , cancellationToken ) ;
187
+ }
188
+
189
+ // If package source reached end, skip it from next probing.
190
+ if ( sourceSearchPackageCount < options . PageSize )
191
+ return false ;
192
+
193
+ return true ;
194
+ }
195
+
196
+ private Task < IEnumerable < IPackageSearchMetadata > > SearchAsync ( PackageSearchResource search , string searchText , SearchOptions options , CancellationToken cancellationToken )
197
+ => search . SearchAsync ( searchText , new SearchFilter ( options . IsPrereleaseIncluded ) , options . PageIndex * options . PageSize , options . PageSize , nuGetLog , cancellationToken ) ;
198
+
177
199
private async Task AddPackageAsync ( List < IPackage > result , SourceRepository repository , IPackageSearchMetadata package , bool isPrereleaseIncluded , CancellationToken cancellationToken )
178
200
{
179
201
NuGetPackageFilterResult filterResult = await filter . IsPassedAsync ( repository , package , cancellationToken ) ;
0 commit comments