@@ -259,13 +259,12 @@ func InstallWithProgress(cliPkgs, caskPkgs []string, dryRun bool) (installedForm
259259 var allFailed []failedJob
260260
261261 if len (newCli ) > 0 {
262- ui . Info ( fmt . Sprintf ( " Installing %d CLI packages..." , len (newCli ) ))
262+ progress . PrintLine ( " Installing %d CLI packages via brew install ..." , len (newCli ))
263263
264264 args := append ([]string {"install" }, newCli ... )
265265 cmd := brewInstallCmd (args ... )
266- cmd .Stdout = os .Stdout
267- cmd .Stderr = os .Stderr
268- cmdErr := cmd .Run ()
266+ cmdOutput , cmdErr := cmd .CombinedOutput ()
267+ cmdOutputStr := string (cmdOutput )
269268
270269 // Re-check installed packages to determine actual success
271270 postFormulae , _ , postErr := GetInstalledPackages ()
@@ -278,7 +277,7 @@ func InstallWithProgress(cliPkgs, caskPkgs []string, dryRun bool) (installedForm
278277 } else {
279278 allFailed = append (allFailed , failedJob {
280279 installJob : installJob {name : pkg , isCask : false },
281- errMsg : "install failed" ,
280+ errMsg : parseBrewError ( cmdOutputStr ) ,
282281 })
283282 }
284283 }
@@ -292,26 +291,25 @@ func InstallWithProgress(cliPkgs, caskPkgs []string, dryRun bool) (installedForm
292291 } else {
293292 allFailed = append (allFailed , failedJob {
294293 installJob : installJob {name : pkg , isCask : false },
295- errMsg : "install failed" ,
294+ errMsg : extractPackageError ( cmdOutputStr , pkg ) ,
296295 })
297296 }
298297 }
299298 }
300299 }
301300
302301 if len (newCask ) > 0 {
303- ui . Info ( fmt . Sprintf ( " Installing %d GUI apps..." , len (newCask ) ))
302+ progress . PrintLine ( " Installing %d GUI apps via brew install --cask ..." , len (newCask ))
304303
305304 args := append ([]string {"install" , "--cask" }, newCask ... )
306305 cmd := brewInstallCmd (args ... )
307- cmd .Stdout = os .Stdout
308- cmd .Stderr = os .Stderr
309306 // Open TTY for password prompts
310307 tty , opened := system .OpenTTY ()
311308 if opened {
312309 cmd .Stdin = tty
313310 }
314- cmdErr := cmd .Run ()
311+ cmdOutput , cmdErr := cmd .CombinedOutput ()
312+ cmdOutputStr := string (cmdOutput )
315313 if opened {
316314 tty .Close ()
317315 }
@@ -327,7 +325,7 @@ func InstallWithProgress(cliPkgs, caskPkgs []string, dryRun bool) (installedForm
327325 } else {
328326 allFailed = append (allFailed , failedJob {
329327 installJob : installJob {name : pkg , isCask : true },
330- errMsg : "install failed" ,
328+ errMsg : parseBrewError ( cmdOutputStr ) ,
331329 })
332330 }
333331 }
@@ -341,7 +339,7 @@ func InstallWithProgress(cliPkgs, caskPkgs []string, dryRun bool) (installedForm
341339 } else {
342340 allFailed = append (allFailed , failedJob {
343341 installJob : installJob {name : pkg , isCask : true },
344- errMsg : "install failed" ,
342+ errMsg : extractPackageError ( cmdOutputStr , pkg ) ,
345343 })
346344 }
347345 }
@@ -418,36 +416,6 @@ type failedJob struct {
418416 errMsg string
419417}
420418
421- func installCaskWithProgress (pkg string , progress * ui.StickyProgress ) string {
422- progress .PauseForInteractive ()
423-
424- cmd := brewInstallCmd ("install" , "--cask" , pkg )
425- tty , opened := system .OpenTTY ()
426- if opened {
427- defer tty .Close ()
428- }
429- cmd .Stdin = tty
430- cmd .Stdout = os .Stdout
431- cmd .Stderr = os .Stderr
432- err := cmd .Run ()
433-
434- progress .ResumeAfterInteractive ()
435-
436- if err != nil {
437- return "install failed"
438- }
439- return ""
440- }
441-
442- func printBrewOutput (output string , progress * ui.StickyProgress ) {
443- for _ , line := range strings .Split (strings .TrimSpace (output ), "\n " ) {
444- line = strings .TrimSpace (line )
445- if line != "" {
446- progress .PrintLine (" %s" , line )
447- }
448- }
449- }
450-
451419func brewInstallCmd (args ... string ) * exec.Cmd {
452420 cmd := exec .Command ("brew" , args ... )
453421 cmd .Env = append (os .Environ (), "HOMEBREW_NO_AUTO_UPDATE=1" )
@@ -585,6 +553,31 @@ func parseBrewError(output string) string {
585553 }
586554}
587555
556+ // extractPackageError tries to find an error message specific to pkg in the
557+ // combined brew output. Falls back to parseBrewError on the full output.
558+ func extractPackageError (output , pkg string ) string {
559+ // Scan for lines mentioning the package name near an error indicator.
560+ lowerPkg := strings .ToLower (pkg )
561+ for _ , line := range strings .Split (output , "\n " ) {
562+ lower := strings .ToLower (line )
563+ if strings .Contains (lower , lowerPkg ) && strings .Contains (lower , "error" ) {
564+ line = strings .TrimSpace (line )
565+ if len (line ) > 80 {
566+ return line [:77 ] + "..."
567+ }
568+ return line
569+ }
570+ }
571+
572+ // No package-specific line found; fall back to the general parser but
573+ // indicate the package was not installed after the batch attempt.
574+ parsed := parseBrewError (output )
575+ if parsed == "unknown error" {
576+ return "not installed after batch attempt"
577+ }
578+ return parsed
579+ }
580+
588581func Uninstall (packages []string , dryRun bool ) error {
589582 if len (packages ) == 0 {
590583 return nil
0 commit comments