Effettuare un brew upgrade completo

(pubblicato il 25 marzo 2021) laptop Photo by olia danilevich on Pexels.com

Sul Mac trovo comodo usare brew . Permette di gestire tante applicazioni con un gestore di pacchetti.

In passato, eseguivo l’update / upgrade delle formule e l’upgrade dei cask.

Col tempo, la gestione dei cask è diventata più omogenea con quella delle formule ma l’update / upgrade mi rimane ancora un po’ misterioso.

Eseguendo un brew update && brew upgrade, soprattutto dalle ultime versioni (dalla 3.0.7 in poi di sicuro), l’update sembra fare il suo lavoro e trova un po’ di cask aggiornare.

Càpita però che l’upgrade ne aggiorni qualcuno, un brew upgrade --cask ne aggiorni qualcun altro (senza raggiungere il totale iniziale) e provando a rifare l’update subito dopo (e anche l’upgrade) il sistema rimane intatto come se fosse up-to-date.

Agendo puntualmente sul cask invece, l’aggiornamento parte eccome. Come se fossero rimaste in cache delle informazioni discordanti sullo stato reale dell’applicazione e su quello potenziale.

Ho cercato un po’ in rete, sembra un problema comune.

Al solito, è partito lo script.

#!/usr/bin/bash
echo -e '\E[37;44m'"\033[1m***************\033[0m"
echo -e '\E[37;44m'"\033[1m* brew update *\033[0m"
echo -e '\E[37;44m'"\033[1m***************\033[0m"
brew update
 
 
echo -e "\n"
echo -e '\E[37;44m'"\033[1m****************\033[0m"
echo -e '\E[37;44m'"\033[1m* brew upgrade *\033[0m"
echo -e '\E[37;44m'"\033[1m****************\033[0m"
if [[ -z $(brew upgrade) ]]; then
    echo -e "Nothing."
fi
 
 
echo -e "\n"
echo -e '\E[37;44m'"\033[1m***********************\033[0m"
echo -e '\E[37;44m'"\033[1m* brew upgrade --cask *\033[0m"
echo -e '\E[37;44m'"\033[1m***********************\033[0m"
for c in $(brew list --cask -1); do
    printf %-30s "$c"
    info=$(brew info --cask "$c")
     
    current_ver=$(head -n1 <<< "$info" | cut -d " " -f 2)
    installed_ver=$(head -n3 <<< "$info" | tail -n1 | cut -d"/" -f 6 | cut -d " " -f 1)
     
    if [ "$installed_ver" != "$current_ver" ]; then
        answer=""
        while [[ -z $answer ]]; do
         
        read -r -p "$c installed version is '$installed_ver', but the current version is '$current_ver'. Do you want to upgrade $c? ["$'\e[;32;1mYES\e[0m/no] ' answer
 
        case ${answer,,} in
            yes|"")
                brew upgrade --cask --force $c
                answer="yes"
                ;;
            no)
                echo "Installation of $c $current_ver skipped"
                ;;
            *)
                answer=""
                ;;
            esac
        done
    else
        printf ": \033[38;5;70mis up-to-date (ver. $installed_ver)\033[0m\n"
    fi
done
 
 
echo -e "\n"
echo -e '\E[37;44m'"\033[1m****************\033[0m"
echo -e '\E[37;44m'"\033[1m* brew cleanup *\033[0m"
echo -e '\E[37;44m'"\033[1m****************\033[0m"
if [[ -z $(brew cleanup) ]]; then
    echo -e "Nothing."
fi
 
 
echo -e "\n"
echo -e '\E[37;44m'"\033[1m***************\033[0m"
echo -e '\E[37;44m'"\033[1m* brew doctor *\033[0m"
echo -e '\E[37;44m'"\033[1m***************\033[0m"
brew doctor

Al di là dello zucchero sintattico, la soluzione è stata brutale e ruvida: un ciclo sulla lista dei cask con il force sull’upgrade (righe 21-50). La cosa ancora più singolare è che in questo modo vengono aggiornati dei cask che non risultavano nemmeno nel primo upgrade.

Sicuramente si potrà fare anche meglio. [2]

  1. Ho provato a usare brew livecheck per recuperare più elegantemente le info nelle righe 25-26 ma mi dà qualche problema, ogni tanto va in crash. Ho optato per la scansione secca della lista.
  2. Non so bene come lavori brew outdated, se soffra degli stessi problemi degli altri comandi (sospetto di sì ma devo verificare).
  3. In realtà basterebbe una sola riga:
brew list --cask|xargs brew upgrade --cask

solo che così non riesco a controllare il numero di versione causando un aggiornamento quasi sempre inutile per tutti quei cask che hanno come versione “latest” (come Cisco Webex)

Lo script fa il suo lavoro ma ho trovato anche questa alternativa (decisamente più elegante): https://github.com/buo/homebrew-cask-upgrade

Un comando esterno, brew cu nella sua forma compatta, che sostituisce ed estende le funzionalità di brew upgrade. Avendo aggiornato da poco, non l’ho ancora visto all’opera.

Edit (31/03/2021):

In realtà, leggendo anche il man e il log dell’applicazione su stdout, ho capito che il funzionamento di brew è corretto.

upgrade e outadated prendono in esame solo i cask che non dispongono di autoupdate.

==> Casks with ‘auto_updates’ or ‘version :latest’ will not be upgraded; pass --greedy to upgrade them.

Un atteggiamento prudenziale che è facile comprendere. Laddove sia disponibile una funzionalità di autoupdate, si preferisce che sia l’applicazione stessa a gestire questo aspetto, lasciando a brew upgrade --cask (e ai file .rb di configurazione del cask, di conseguenza) la gestione di tutto il resto.

In questo modo, i cask che possono autoaggiornarsi, possono farlo in autonomia appena possibile, senza dipendere dalla modifica necessaria al file di configurazione che innesca l’aggiornamento.

Volendo bypassare questo comportamento, si può ricorrere all’opzione --greedy che forza l’upgrade sia per le app con autoupdate che per quelle che gestiscono il numero di versione con l’orrendo “latest”

Quindi:

brew outdated --greedy --cask

e

brew upgrade --greedy --cask

permettono rispettivamente:

Forzando l’aggiornamento in questo modo, si potrà andare incontro ad un disallineamento, tipo:

N.B. brew cu funziona benissimo permettendo di gestire separatamente sia l’autoupdate che il latest

Note all’articolo

  1. No, non fa cilecca [↵]
  2. Ho fatto fuori il ciclo (e non solo) proprio qui [↵]

#brew #bash #macos #scripting