11using System . Diagnostics ;
22using System . Text ;
3+ using System . Text . Json ;
4+ using System . Text . Json . Serialization ;
35using System . Text . RegularExpressions ;
46using UniGetUI . Core . Logging ;
57using UniGetUI . Core . Tools ;
1113
1214namespace UniGetUI . PackageEngine . Managers . WingetManager ;
1315
14- internal sealed class WinGetCliHelper : IWinGetManagerHelper
16+ internal sealed partial class WinGetCliHelper : IWinGetManagerHelper
1517{
1618 // "winget search a" returns ~12k results; cap to the most relevant to avoid the freeze/RAM spike.
1719 private const int MAX_SEARCH_RESULTS = 100 ;
@@ -270,6 +272,80 @@ IEnumerable<string> outputLines
270272 }
271273
272274 public IReadOnlyList < Package > FindPackages_UnSafe ( string query )
275+ {
276+ if ( query . Length == 0 )
277+ {
278+ return GetSourcesForBrowse ( )
279+ . SelectMany ( source => SearchPackages ( query , source , SearchLimits . MaxEmptyQueryResultsPerSource ) )
280+ . ToArray ( ) ;
281+ }
282+
283+ return SearchPackages ( query , null , MAX_SEARCH_RESULTS ) ;
284+ }
285+
286+ private List < IManagerSource > GetSourcesForBrowse ( )
287+ {
288+ using var _cliLock = WinGet . AcquireCliLock ( ) ;
289+ List < IManagerSource > sources = [ ] ;
290+ using Process p = new ( )
291+ {
292+ StartInfo = new ( )
293+ {
294+ FileName = _cliExecutablePath ,
295+ Arguments = Manager . Status . ExecutableCallArgs + " source export" ,
296+ RedirectStandardOutput = true ,
297+ RedirectStandardError = true ,
298+ UseShellExecute = false ,
299+ CreateNoWindow = true ,
300+ StandardOutputEncoding = Encoding . UTF8 ,
301+ } ,
302+ } ;
303+
304+ IProcessTaskLogger logger = Manager . TaskLogger . CreateNew ( LoggableTaskType . ListSources , p ) ;
305+
306+ if ( CoreTools . IsAdministrator ( ) )
307+ {
308+ string WinGetTemp = AppPaths . RedirectTempToElevatedDirectory ( p . StartInfo ) ;
309+ logger . AddToStdErr (
310+ $ "[WARN] Redirecting %TEMP% folder to { WinGetTemp } , since UniGetUI was run as admin"
311+ ) ;
312+ }
313+
314+ p . Start ( ) ;
315+
316+ foreach ( string name in ParseExportedSourceNames ( ReadOutputLines ( p , logger ) ) )
317+ {
318+ sources . Add ( Manager . SourcesHelper . Factory . GetSourceOrDefault ( name ) ) ;
319+ }
320+
321+ logger . AddToStdErr ( p . StandardError . ReadToEnd ( ) ) ;
322+ p . WaitForExit ( ) ;
323+ logger . Close ( p . ExitCode ) ;
324+ return sources ;
325+ }
326+
327+ internal static IEnumerable < string > ParseExportedSourceNames ( IEnumerable < string > outputLines )
328+ {
329+ foreach ( string line in outputLines )
330+ {
331+ string ? name ;
332+ try
333+ {
334+ name = JsonSerializer . Deserialize ( line , WinGetCliJsonContext . Default . WinGetExportedSource ) ? . Name ;
335+ }
336+ catch ( JsonException )
337+ {
338+ continue ;
339+ }
340+
341+ if ( ! string . IsNullOrWhiteSpace ( name ) )
342+ {
343+ yield return name ;
344+ }
345+ }
346+ }
347+
348+ private List < Package > SearchPackages ( string query , IManagerSource ? source , int count )
273349 {
274350 using var _cliLock = WinGet . AcquireCliLock ( ) ;
275351 List < Package > Packages = [ ] ;
@@ -282,8 +358,10 @@ public IReadOnlyList<Package> FindPackages_UnSafe(string query)
282358 Manager . Status . ExecutableCallArgs
283359 + " search \" "
284360 + query
285- + "\" --count "
286- + MAX_SEARCH_RESULTS
361+ + "\" "
362+ + ( source is null ? "" : " --source \" " + source . Name + "\" " )
363+ + " --count "
364+ + count
287365 + " --accept-source-agreements "
288366 + WinGet . GetProxyArgument ( ) ,
289367 RedirectStandardOutput = true ,
@@ -306,7 +384,7 @@ public IReadOnlyList<Package> FindPackages_UnSafe(string query)
306384
307385 p . Start ( ) ;
308386
309- Packages . AddRange ( ParseFoundPackages ( Manager , ReadOutputLines ( p , logger ) ) ) ;
387+ Packages . AddRange ( ParseFoundPackages ( Manager , ReadOutputLines ( p , logger ) , source ) ) ;
310388
311389 logger . AddToStdErr ( p . StandardError . ReadToEnd ( ) ) ;
312390 p . WaitForExit ( ) ;
@@ -317,7 +395,8 @@ public IReadOnlyList<Package> FindPackages_UnSafe(string query)
317395
318396 internal static IReadOnlyList < Package > ParseFoundPackages (
319397 WinGet manager ,
320- IEnumerable < string > outputLines
398+ IEnumerable < string > outputLines ,
399+ IManagerSource ? queriedSource = null
321400 )
322401 {
323402 List < Package > packages = [ ] ;
@@ -338,7 +417,7 @@ IEnumerable<string> outputLines
338417
339418 IManagerSource source =
340419 sourceName . Length == 0
341- ? manager . DefaultSource
420+ ? queriedSource ?? manager . DefaultSource
342421 : manager . SourcesHelper . Factory . GetSourceOrDefault ( sourceName ) ;
343422
344423 packages . Add ( new Package ( name , id , version , source , manager ) ) ;
@@ -512,4 +591,9 @@ public IReadOnlyList<IManagerSource> GetSources_UnSafe()
512591 logger . Close ( p . ExitCode ) ;
513592 return sources ;
514593 }
594+
595+ internal sealed record WinGetExportedSource ( string ? Name ) ;
596+
597+ [ JsonSerializable ( typeof ( WinGetExportedSource ) ) ]
598+ internal sealed partial class WinGetCliJsonContext : JsonSerializerContext { }
515599}
0 commit comments