@@ -4,93 +4,164 @@ set -eu
44DEVSTACK_APP=" /Applications/DevStackMenu.app"
55IMPORTER_APP=" /Applications/Import Compose To DX.app"
66DX_BINARY=" /usr/local/bin/dx"
7+ STATE_DIR=" /private/tmp/devstackmenu-installer"
8+ POLICY_FILE=" $STATE_DIR /policy"
9+ BACKUP_DIR=" $STATE_DIR /backup"
710
8- HAVE_EXISTING=0
9- [ -d " $DEVSTACK_APP " ] && HAVE_EXISTING=1
10- [ -d " $IMPORTER_APP " ] && HAVE_EXISTING=1
11- [ -e " $DX_BINARY " ] && HAVE_EXISTING=1
11+ ensure_state_dir () {
12+ rm -rf " $STATE_DIR "
13+ mkdir -p " $BACKUP_DIR "
14+ }
1215
13- if [ " $HAVE_EXISTING " -eq 0 ]; then
14- exit 0
15- fi
16-
17- DEVSTACK_VERSION=" unknown"
18- if [ -f " $DEVSTACK_APP /Contents/Info.plist" ]; then
19- DEVSTACK_VERSION=" $( /usr/libexec/PlistBuddy -c " Print :CFBundleShortVersionString" " $DEVSTACK_APP /Contents/Info.plist" 2> /dev/null || true) "
20- DEVSTACK_VERSION=" ${DEVSTACK_VERSION:- unknown} "
21- fi
22-
23- DX_VERSION=" unknown"
24- if [ -f " $DX_BINARY " ]; then
25- if DX_HELPER_OUTPUT=" $( " $DX_BINARY " --version 2> /dev/null || true) " ; then
26- DX_VERSION=" $DX_HELPER_OUTPUT "
16+ path_present () {
17+ if [ -e " $1 " ]; then
18+ printf ' yes'
2719 else
28- DX_VERSION= " installed "
20+ printf ' no '
2921 fi
30- fi
31-
32- echo " Existing DevStack installation detected."
33- echo " - $DEVSTACK_APP (version: $DEVSTACK_VERSION )"
34- echo " - $IMPORTER_APP (installed: $( [ -d \" $IMPORTER_APP \" ] && echo yes || echo no) )"
35- echo " - $DX_BINARY (installed: $( [ -e \" $DX_BINARY \" ] && echo yes || echo no) , version: $DX_VERSION )"
36- echo
37-
38- if [ " ${DEVSTACK_INSTALL_EXISTING_POLICY:- } " = " remove" ]; then
39- CHOICE=" remove"
40- elif [ " ${DEVSTACK_INSTALL_EXISTING_POLICY:- } " = " keep" ] || [ " ${DEVSTACK_INSTALL_EXISTING_POLICY:- } " = " skip" ]; then
41- CHOICE=" keep"
42- elif [ " ${DEVSTACK_INSTALL_EXISTING_POLICY:- } " = " abort" ]; then
43- CHOICE=" abort"
44- else
45- CHOICE=" "
46- fi
22+ }
4723
48- if [ -z " $CHOICE " ] && [ ! -t 0 ]; then
49- echo " Non-interactive install: keeping existing installation and cancelling package install."
50- echo " Re-run with DEVSTACK_INSTALL_EXISTING_POLICY=remove to replace existing installation."
51- exit 1
52- fi
53-
54- if [ -z " $CHOICE " ] && [ -r /dev/tty ]; then
24+ prompt_in_tty () {
5525 while true ; do
56- printf " Choose action: [r] Remove existing and install / [k] Keep existing unchanged (cancel install) / [a] Abort: "
57- if ! IFS= read -r CHOICE < /dev/tty ; then
58- echo " Could not read decision. Cancelling install. " >&2
59- exit 1
26+ printf " Existing DevStack installation found. Choose action: [r] Replace / [k] Keep unchanged / [a] Abort: "
27+ if ! IFS= read -r choice ; then
28+ printf ' abort\n '
29+ return
6030 fi
61- case " $CHOICE " in
31+
32+ case " $choice " in
6233 r|R)
63- CHOICE= " remove"
64- break
34+ printf ' remove\n '
35+ return
6536 ;;
6637 k|K)
67- CHOICE= " keep"
68- break
38+ printf ' keep\n '
39+ return
6940 ;;
7041 a|A)
71- CHOICE=" abort"
72- break
73- ;;
74- * )
75- echo " Invalid choice: $CHOICE "
42+ printf ' abort\n'
43+ return
7644 ;;
7745 esac
7846 done
47+ }
48+
49+ prompt_in_gui () {
50+ console_user=" $( stat -f %Su /dev/console 2> /dev/null || printf ' %s' root) "
51+ if [ -z " $console_user " ] || [ " $console_user " = " root" ]; then
52+ return 1
53+ fi
54+
55+ console_uid=" $( id -u " $console_user " 2> /dev/null || true) "
56+ if [ -z " $console_uid " ]; then
57+ return 1
58+ fi
59+
60+ result=" $(
61+ /bin/launchctl asuser " $console_uid " /usr/bin/osascript \
62+ -e ' button returned of (display dialog "Existing DevStack installation found.\n\nReplace it with this package or keep the current installation unchanged?" with title "DevStackMenu Installer" buttons {"Abort", "Keep", "Replace"} default button "Replace" cancel button "Abort" with icon caution)' \
63+ 2> /dev/null || true
64+ ) "
65+
66+ case " $result " in
67+ Replace)
68+ printf ' remove\n'
69+ return
70+ ;;
71+ Keep)
72+ printf ' keep\n'
73+ return
74+ ;;
75+ * )
76+ printf ' abort\n'
77+ return
78+ ;;
79+ esac
80+ }
81+
82+ resolve_choice () {
83+ case " ${DEVSTACK_INSTALL_EXISTING_POLICY:- } " in
84+ remove)
85+ printf ' remove\n'
86+ return
87+ ;;
88+ keep|skip)
89+ printf ' keep\n'
90+ return
91+ ;;
92+ abort)
93+ printf ' abort\n'
94+ return
95+ ;;
96+ " " )
97+ ;;
98+ * )
99+ echo " Invalid DEVSTACK_INSTALL_EXISTING_POLICY: ${DEVSTACK_INSTALL_EXISTING_POLICY} " >&2
100+ printf ' abort\n'
101+ return
102+ ;;
103+ esac
104+
105+ if [ -t 0 ] && [ -t 1 ]; then
106+ prompt_in_tty
107+ return
108+ fi
109+
110+ if prompt_in_gui; then
111+ return
112+ fi
113+
114+ printf ' abort\n'
115+ }
116+
117+ backup_path_if_present () {
118+ source_path=" $1 "
119+ backup_name=" $2 "
120+
121+ if [ -e " $source_path " ]; then
122+ /usr/bin/ditto " $source_path " " $BACKUP_DIR /$backup_name "
123+ fi
124+ }
125+
126+ has_existing_installation=0
127+ [ -e " $DEVSTACK_APP " ] && has_existing_installation=1
128+ [ -e " $IMPORTER_APP " ] && has_existing_installation=1
129+ [ -e " $DX_BINARY " ] && has_existing_installation=1
130+
131+ ensure_state_dir
132+
133+ if [ " $has_existing_installation " -eq 0 ]; then
134+ printf ' install\n' > " $POLICY_FILE "
135+ exit 0
79136fi
80137
81- case " $CHOICE " in
138+ echo " Existing DevStack installation detected."
139+ echo " - $DEVSTACK_APP : $( path_present " $DEVSTACK_APP " ) "
140+ echo " - $IMPORTER_APP : $( path_present " $IMPORTER_APP " ) "
141+ echo " - $DX_BINARY : $( path_present " $DX_BINARY " ) "
142+
143+ choice=" $( resolve_choice) "
144+ printf ' %s\n' " $choice " > " $POLICY_FILE "
145+
146+ case " $choice " in
82147 remove)
83148 [ -d " $DEVSTACK_APP " ] && rm -rf " $DEVSTACK_APP "
84149 [ -d " $IMPORTER_APP " ] && rm -rf " $IMPORTER_APP "
85150 [ -e " $DX_BINARY " ] && rm -f " $DX_BINARY "
86- echo " Existing DevStack files removed. Continuing with installation."
151+ echo " Replacing existing DevStack installation."
152+ ;;
153+ keep)
154+ backup_path_if_present " $DEVSTACK_APP " " DevStackMenu.app"
155+ backup_path_if_present " $IMPORTER_APP " " Import Compose To DX.app"
156+ backup_path_if_present " $DX_BINARY " " dx"
157+ echo " Keeping existing DevStack installation unchanged."
87158 ;;
88- keep| abort| " " )
89- echo " Keeping existing installation. Cancelling package installation ."
159+ abort)
160+ echo " Installation aborted by user ."
90161 exit 1
91162 ;;
92163 * )
93- echo " Invalid policy ' $CHOICE '. Cancelling installation. "
164+ echo " Unknown install policy: $choice " >&2
94165 exit 1
95166 ;;
96167esac
0 commit comments