@@ -21,13 +21,6 @@ public partial class Cargo : PackageManager
2121 [ GeneratedRegex ( @"([\w-]+)\s=\s""(\d+\.\d+\.\d+)""\s*#\s(.*)" ) ]
2222 private static partial Regex SearchLineRegex ( ) ;
2323
24- [ GeneratedRegex ( @"(.+)v(\d+\.\d+\.\d+)\s*v(\d+\.\d+\.\d+)\s*(Yes|No)" ) ]
25- private static partial Regex UpdateLineRegex ( ) ;
26-
27- // Matches "ripgrep v15.1.0:" lines from `cargo install --list`
28- [ GeneratedRegex ( @"^([\w-]+)\s+v(\d+\.\d+\.\d+):" ) ]
29- private static partial Regex InstallListLineRegex ( ) ;
30-
3124 public Cargo ( )
3225 {
3326 string cargoCommand = OperatingSystem . IsWindows ( ) ? "cargo.exe" : "cargo" ;
@@ -193,28 +186,44 @@ protected override void _loadManagerVersion(out string version)
193186 }
194187
195188 public void InvalidateInstalledCache ( ) =>
196- TaskRecycler < List < Match > > . RemoveFromCache ( GetInstalledCommandOutput ) ;
189+ TaskRecycler < List < CargoListEntry > > . RemoveFromCache ( GetInstalledCommandOutput ) ;
197190
198191 private IReadOnlyList < Package > GetPackages ( LoggableTaskType taskType )
199192 {
200193 List < Package > Packages = [ ] ;
201- foreach ( var match in TaskRecycler < List < Match > > . RunOrAttach ( GetInstalledCommandOutput , 15 ) )
194+ var entries = TaskRecycler < List < CargoListEntry > > . RunOrAttach ( GetInstalledCommandOutput , 15 ) ;
195+ foreach ( var entry in entries )
202196 {
203- var id = match . Groups [ 1 ] ? . Value ? . Trim ( ) ?? "" ;
204- var name = CoreTools . FormatAsName ( id ) ;
205- var oldVersion = match . Groups [ 2 ] ? . Value ? . Trim ( ) ?? "" ;
206- var newVersion = match . Groups [ 3 ] ? . Value ? . Trim ( ) ?? "" ;
207- if ( taskType is LoggableTaskType . ListUpdates && oldVersion != newVersion )
208- Packages . Add ( new Package ( name , id , oldVersion , newVersion , DefaultSource , this ) ) ;
197+ var name = CoreTools . FormatAsName ( entry . Id ) ;
198+ if ( taskType is LoggableTaskType . ListUpdates )
199+ {
200+ if (
201+ entry . NeedsUpdate
202+ && entry . LatestVersion is { Length : > 0 } latestVersion
203+ && latestVersion != entry . InstalledVersion
204+ )
205+ Packages . Add (
206+ new Package (
207+ name ,
208+ entry . Id ,
209+ entry . InstalledVersion ,
210+ latestVersion ,
211+ DefaultSource ,
212+ this
213+ )
214+ ) ;
215+ }
209216 else if ( taskType is LoggableTaskType . ListInstalledPackages )
210- Packages . Add ( new Package ( name , id , oldVersion , DefaultSource , this ) ) ;
217+ Packages . Add (
218+ new Package ( name , entry . Id , entry . InstalledVersion , DefaultSource , this )
219+ ) ;
211220 }
212221 return Packages ;
213222 }
214223
215- private List < Match > GetInstalledCommandOutput ( )
224+ private List < CargoListEntry > GetInstalledCommandOutput ( )
216225 {
217- List < Match > output = [ ] ;
226+ List < string > stdout = [ ] ;
218227 using Process p = GetProcess ( Status . ExecutablePath , "install-update --list" ) ;
219228 IProcessTaskLogger logger = TaskLogger . CreateNew ( LoggableTaskType . OtherTask , p ) ;
220229 logger . AddToStdOut ( "Other task: Call the install-update command" ) ;
@@ -224,38 +233,39 @@ private List<Match> GetInstalledCommandOutput()
224233 while ( ( line = p . StandardOutput . ReadLine ( ) ) is not null )
225234 {
226235 logger . AddToStdOut ( line ) ;
227- var match = UpdateLineRegex ( ) . Match ( line ) ;
228- if ( match . Success )
229- output . Add ( match ) ;
236+ stdout . Add ( line ) ;
230237 }
231238 logger . AddToStdErr ( p . StandardError . ReadToEnd ( ) ) ;
232239 p . WaitForExit ( ) ;
240+
241+ List < string > skippedRows = [ ] ;
242+ var output = ParseInstallUpdateList ( stdout , skippedRows ) ;
243+ foreach ( var skippedRow in skippedRows )
244+ logger . AddToStdErr ( $ "Ignored unrecognized `install-update --list` row: { skippedRow } ") ;
233245 logger . Close ( p . ExitCode ) ;
234246
235247 if ( output . Count > 0 )
236248 return output ;
237249
238- // Fallback: cargo-update is not installed, use the built-in `cargo install --list`.
239- // No latest-version info is available, so updates won't be detected, but the installed
240- // packages list will be populated correctly.
250+ List < string > fallbackStdout = [ ] ;
241251 using Process fallback = GetProcess ( Status . ExecutablePath , "install --list" ) ;
242- IProcessTaskLogger fallbackLogger = TaskLogger . CreateNew ( LoggableTaskType . OtherTask , fallback ) ;
243- fallbackLogger . AddToStdOut ( "Falling back to `cargo install --list` (cargo-update not available)" ) ;
252+ IProcessTaskLogger fallbackLogger = TaskLogger . CreateNew (
253+ LoggableTaskType . OtherTask ,
254+ fallback
255+ ) ;
256+ fallbackLogger . AddToStdOut (
257+ "Falling back to `cargo install --list` (cargo-update reported no packages)"
258+ ) ;
244259 fallback . Start ( ) ;
245260 while ( ( line = fallback . StandardOutput . ReadLine ( ) ) is not null )
246261 {
247262 fallbackLogger . AddToStdOut ( line ) ;
248- var m = InstallListLineRegex ( ) . Match ( line ) ;
249- if ( ! m . Success ) continue ;
250- // Synthesise a match compatible with UpdateLineRegex (same installed and latest version → no update)
251- var fake = UpdateLineRegex ( ) . Match ( $ "{ m . Groups [ 1 ] . Value } v{ m . Groups [ 2 ] . Value } v{ m . Groups [ 2 ] . Value } No") ;
252- if ( fake . Success )
253- output . Add ( fake ) ;
263+ fallbackStdout . Add ( line ) ;
254264 }
255265 fallbackLogger . AddToStdErr ( fallback . StandardError . ReadToEnd ( ) ) ;
256266 fallback . WaitForExit ( ) ;
257267 fallbackLogger . Close ( fallback . ExitCode ) ;
258- return output ;
268+ return ParseInstallList ( fallbackStdout ) ;
259269 }
260270
261271 private Process GetProcess ( string fileName , string extraArguments )
0 commit comments