Skip to content

Instantly share code, notes, and snippets.

@ilfuriano
Last active July 3, 2025 07:46
Show Gist options
  • Save ilfuriano/7739d6933bac82e780facd1ac3f06e36 to your computer and use it in GitHub Desktop.
Save ilfuriano/7739d6933bac82e780facd1ac3f06e36 to your computer and use it in GitHub Desktop.
Flutter Helper
#!/bin/bash
# --- fh.sh - Un helper per i comandi Flutter con FVM e Flavors ---
# Versione con ridenominazione, rilevamento FVM e conversione nomi flavor (snake_case -> camelCase) PORTABILE.
#
# (Il resto dell'intestazione e i colori rimangono invariati)
# ...
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
# --- Estrazione del nome del progetto da pubspec.yaml ---
# (invariato)
if [ ! -f "pubspec.yaml" ]; then
echo -e "${RED}Errore: file 'pubspec.yaml' non trovato.${NC}"
echo "Assicurati di eseguire questo script dalla directory principale del tuo progetto Flutter."
exit 1
fi
PROJECT_NAME=$(grep '^[[:space:]]*name:' pubspec.yaml | cut -d ':' -f 2 | xargs)
if [ -z "$PROJECT_NAME" ]; then
echo -e "${RED}Errore: Impossibile estrarre il nome del progetto da pubspec.yaml.${NC}"
exit 1
fi
echo -e "${GREEN}Progetto rilevato: ${YELLOW}${PROJECT_NAME}${NC}"
# --- Rilevamento automatico FVM ---
# (invariato)
FLUTTER_CMD="flutter"
DART_CMD="dart"
if [ -d ".fvm" ]; then
if command -v fvm &> /dev/null; then
FLUTTER_CMD="fvm flutter"
DART_CMD="fvm dart"
echo -e "${GREEN}Rilevata configurazione FVM. I comandi useranno '${YELLOW}fvm${GREEN}'.${NC}"
else
echo -e "${YELLOW}Attenzione: Trovata directory '.fvm' ma il comando 'fvm' non è nel PATH.${NC}"
echo -e "Verrà usato il Flutter di sistema."
fi
else
echo -e "${GREEN}Nessuna configurazione FVM rilevata. Verrà usato il Flutter/Dart di sistema.${NC}"
fi
echo "-----------------------------------------------------"
# --- NUOVO: Funzioni di conversione nome (versione portabile) ---
# Converte una stringa da snake_case (es. dev_ios) a camelCase (es. devIos)
# Usa awk per la massima portabilità (funziona su Linux e macOS)
to_camel_case() {
echo "$1" | awk -F"_" '{for(i=2;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2); print}' OFS=""
}
# Converte una stringa da camelCase (es. devIos) a snake_case (es. dev_ios)
# Questa funzione con sed è già portabile
to_snake_case() {
echo "$1" | sed -e 's/\([A-Z]\)/_\1/g' -e 's/^_//' | tr '[:upper:]' '[:lower:]'
}
# --- Rilevamento automatico dei Flavor con conversione a camelCase ---
# (La logica qui rimane invariata, ma ora usa la funzione corretta)
if [ ! -d "lib" ]; then
echo -e "${RED}Errore: La directory 'lib' non è stata trovata.${NC}"
exit 1
fi
FLAVORS=()
for f in lib/main_*.dart; do
[ -e "$f" ] || continue
flavor_name_base=$(basename "$f" .dart)
snake_case_flavor=${flavor_name_base#main_}
camel_case_flavor=$(to_camel_case "$snake_case_flavor")
FLAVORS+=("$camel_case_flavor")
done
#
# --- TUTTO IL RESTO DELLO SCRIPT RIMANE IDENTICO ---
# Le funzioni usage, rename_artifact, la logica dei comandi, ecc.
# non necessitano di modifiche perché si basano sulle funzioni
# di conversione che abbiamo appena corretto.
#
# --- Funzione di aiuto (Usage) ---
usage() {
echo -e "${GREEN}Flutter Helper (fh) - Gestione comandi, Flavors & Ridenominazione Artefatti${NC}"
echo -e "Lo script rileva automaticamente FVM e gestisce i nomi dei flavor in ${YELLOW}camelCase${NC}."
echo ""
echo -e "${YELLOW}Uso:${NC} ./fh.sh <comando> [flavor] [argomenti_extra...]"
echo " Esempio: ./fh.sh run devIos"
echo ""
echo -e "${YELLOW}Comandi disponibili:${NC}"
echo " run <flavor> Esegue 'flutter run' per il flavor specificato."
echo " apk <flavor> Crea un APK, poi lo rinomina."
echo " appbundle <flavor> Crea un AppBundle, poi lo rinomina."
echo " ipa <flavor> Crea un IPA per iOS (non rinominato)."
echo " apk-all Crea e rinomina un APK per tutti i flavor."
echo " appbundle-all Crea e rinomina un AppBundle per tutti i flavor."
echo " runner Esegue 'dart run build_runner build ...'."
echo " clean Esegue 'flutter clean'."
echo " get Esegue 'flutter pub get'."
echo " help Mostra questo messaggio."
echo ""
if [ ${#FLAVORS[@]} -gt 0 ]; then
echo -e "${YELLOW}Flavor rilevati (in notazione camelCase):${NC}"
for flavor in "${FLAVORS[@]}"; do
original_file="main_$(to_snake_case "$flavor").dart"
echo " - ${flavor} (da ${original_file})"
done
else
echo -e "${RED}Attenzione: Nessun flavor (file main_<flavor>.dart) trovato in lib/.${NC}"
fi
echo ""
}
# --- Funzione per rinominare l'artefatto di build ---
rename_artifact() {
local build_type=$1
local camel_case_flavor=$2
local snake_case_flavor=$(to_snake_case "$camel_case_flavor")
shift 2
local extra_args_str="$*"
local build_mode="debug"
if [[ " ${extra_args_str} " =~ " --release " ]]; then
build_mode="release"
fi
local timestamp=$(date +'%Y%m%d-%H%M%S')
local original_path=""
local extension=""
if [ "$build_type" == "apk" ]; then
extension="apk"
if [ "$build_mode" == "release" ]; then
original_path="build/app/outputs/flutter-apk/app-${snake_case_flavor}-${build_mode}.apk"
else
original_path="build/app/outputs/flutter-apk/app-${build_mode}.apk"
fi
elif [ "$build_type" == "appbundle" ]; then
extension="aab"
original_path="build/app/outputs/bundle/${snake_case_flavor}${build_mode^}/app-${snake_case_flavor}-${build_mode}.aab"
if [ ! -f "$original_path" ]; then
original_path="build/app/outputs/bundle/${snake_case_flavor}Release/app.aab"
fi
else
return
fi
if [ -f "$original_path" ]; then
local new_filename="${PROJECT_NAME}-${camel_case_flavor}-${timestamp}.${extension}"
mv "$original_path" "./$new_filename"
echo -e "${GREEN}Build completata e artefatto rinominato in: ${YELLOW}${new_filename}${NC}"
else
echo -e "${RED}Attenzione: Artefatto non trovato in '$original_path'. La ridenominazione è fallita.${NC}"
fi
}
# --- Validazione Input e Logica Principale ---
if [ "$#" -lt 1 ] || [ "$1" == "help" ]; then
usage
exit 0
fi
COMMAND=$1
# --- Logica per comandi "all" ---
case "$COMMAND" in
apk-all|appbundle-all)
if [ ${#FLAVORS[@]} -eq 0 ]; then
echo -e "${RED}Errore: Nessun flavor trovato. Impossibile eseguire '$COMMAND'.${NC}"
exit 1
fi
shift 1
EXTRA_ARGS=("$@")
BUILD_TYPE=${COMMAND%-all}
echo -e "${GREEN}Inizio la build di '$BUILD_TYPE' per tutti i flavor...${NC}"
[ ${#EXTRA_ARGS[@]} -gt 0 ] && echo -e "${YELLOW}Argomenti extra:${NC} ${EXTRA_ARGS[*]}"
echo "-----------------------------------------------------"
for flavor_camel in "${FLAVORS[@]}"; do
echo -e "\n${GREEN}>>> Costruzione per il flavor: ${YELLOW}${flavor_camel}${NC}"
local flavor_snake=$(to_snake_case "$flavor_camel")
CMD_ARRAY=($FLUTTER_CMD build "$BUILD_TYPE" --flavor "$flavor_snake" -t "lib/main_${flavor_snake}.dart" "${EXTRA_ARGS[@]}")
echo -e "${YELLOW}Comando:${NC} ${CMD_ARRAY[*]}"
echo "---"
"${CMD_ARRAY[@]}"
if [ $? -eq 0 ]; then
rename_artifact "$BUILD_TYPE" "$flavor_camel" "${EXTRA_ARGS[@]}"
else
echo -e "${RED}Errore durante la build per il flavor '$flavor_camel'. Interruzione.${NC}"
exit 1
fi
done
echo -e "\n${GREEN}Tutte le build sono state completate con successo!${NC}"
exit 0
;;
esac
# --- Logica per comandi singoli ---
FLAVOR_CAMEL=$2
shift 2
EXTRA_ARGS=("$@")
is_valid_flavor() {
[[ " ${FLAVORS[*]} " =~ " $1 " ]]
}
require_flavor() {
if [ -z "$FLAVOR_CAMEL" ]; then
echo -e "${RED}Errore: Il comando '$COMMAND' richiede un flavor.${NC}"; usage; exit 1
fi
if ! is_valid_flavor "$FLAVOR_CAMEL"; then
echo -e "${RED}Errore: Flavor '$FLAVOR_CAMEL' non valido.${NC}"; usage; exit 1
fi
}
CMD_ARRAY=()
BUILD_TYPE=""
FLAVOR_SNAKE=$(to_snake_case "$FLAVOR_CAMEL")
case "$COMMAND" in
run)
require_flavor
CMD_ARRAY=($FLUTTER_CMD run --flavor "$FLAVOR_SNAKE" -t "lib/main_${FLAVOR_SNAKE}.dart" "${EXTRA_ARGS[@]}")
;;
apk|appbundle)
require_flavor
BUILD_TYPE=$COMMAND
CMD_ARRAY=($FLUTTER_CMD build "$BUILD_TYPE" --flavor "$FLAVOR_SNAKE" -t "lib/main_${FLAVOR_SNAKE}.dart" "${EXTRA_ARGS[@]}")
;;
ipa)
require_flavor
BUILD_TYPE="ipa"
CMD_ARRAY=($FLUTTER_CMD build ipa --flavor "$FLAVOR_SNAKE" -t "lib/main_${FLAVOR_SNAKE}.dart" "${EXTRA_ARGS[@]}")
;;
runner)
CMD_ARRAY=($DART_CMD run build_runner build --delete-conflicting-outputs "${EXTRA_ARGS[@]}")
;;
clean)
CMD_ARRAY=($FLUTTER_CMD clean)
;;
get)
CMD_ARRAY=($FLUTTER_CMD pub get)
;;
*)
echo -e "${RED}Errore: Comando '$COMMAND' non riconosciuto.${NC}"; usage; exit 1
;;
esac
# Esecuzione del comando
echo -e "${YELLOW}Comando Eseguito:${NC} ${CMD_ARRAY[*]}"
echo "-----------------------------------------------------"
"${CMD_ARRAY[@]}"
# Ridenominazione artefatto
if [[ "$COMMAND" == "apk" || "$COMMAND" == "appbundle" ]]; then
if [ $? -eq 0 ]; then
rename_artifact "$BUILD_TYPE" "$FLAVOR_CAMEL" "${EXTRA_ARGS[@]}"
else
echo -e "${RED}Build fallita. Ridenominazione saltata.${NC}"
fi
fi
@ilfuriano
Copy link
Author

Fixed flavor name calculation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment