@@ -5,21 +5,21 @@ CONFIG_DIR="/boot/firmware"
55DATESTAMP=` date " +%Y-%m-%d-%H-%M-%S" `
66CONFIG_BACKUP=false
77APT_HAS_UPDATED=false
8- RESOURCES_TOP_DIR=$HOME /Pimoroni
9- VENV_BASH_SNIPPET=$RESOURCES_TOP_DIR /auto_venv.sh
10- VENV_DIR=$HOME /.virtualenvs/pimoroni
8+ RESOURCES_TOP_DIR=" $HOME /Pimoroni"
9+ VENV_BASH_SNIPPET=" $RESOURCES_TOP_DIR /auto_venv.sh"
10+ VENV_DIR=" $HOME /.virtualenvs/pimoroni"
1111WD=` pwd`
1212USAGE=" ./install.sh (--unstable)"
1313POSITIONAL_ARGS=()
1414FORCE=false
1515UNSTABLE=false
1616PYTHON=" python"
17+ CMD_ERRORS=false
1718
1819
1920user_check () {
2021 if [ $( id -u) -eq 0 ]; then
21- printf " Script should not be run as root. Try './install.sh'\n"
22- exit 1
22+ fatal " Script should not be run as root. Try './install.sh'\n"
2323 fi
2424}
2525
@@ -54,29 +54,34 @@ inform() {
5454}
5555
5656warning () {
57- echo -e " $( tput setaf 1) $1 $( tput sgr0) "
57+ echo -e " $( tput setaf 1) ⚠ WARNING:$( tput sgr0) $1 "
58+ }
59+
60+ fatal () {
61+ echo -e " $( tput setaf 1) ⚠ FATAL:$( tput sgr0) $1 "
62+ exit 1
5863}
5964
6065find_config () {
6166 if [ ! -f " $CONFIG_DIR /$CONFIG_FILE " ]; then
6267 CONFIG_DIR=" /boot"
63- if [ ! -f " $CONFIG_DIR /$CONFIG_FILE " ]; then
64- warning " Could not find $CONFIG_FILE !"
65- exit 1
68+ if [ ! -f " $CONFIG_DIR /$CONFIG_FILE " ]; then
69+ fatal " Could not find $CONFIG_FILE !"
70+ fi
71+ else
72+ if [ -f " /boot/$CONFIG_FILE " ] && [ ! -L " /boot/$CONFIG_FILE " ]; then
73+ warning " Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR /$CONFIG_FILE "
74+ warning " You might want to fix this!"
6675 fi
67- else
68- if [ -f " /boot/$CONFIG_FILE " ] && [ ! -L " /boot/$CONFIG_FILE " ]; then
69- warning " Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR /$CONFIG_FILE "
70- warning " You might want to fix this!"
71- fi
7276 fi
73- inform " Using $CONFIG_FILE in $CONFIG_DIR "
77+ inform " Using $CONFIG_FILE in $CONFIG_DIR "
7478}
7579
7680venv_bash_snippet () {
77- inform " Checking for $VENV_BASH_SNIPPET \n"
81+ inform " Checking for $VENV_BASH_SNIPPET \n"
7882 if [ ! -f $VENV_BASH_SNIPPET ]; then
79- inform " Creating $VENV_BASH_SNIPPET \n"
83+ inform " Creating $VENV_BASH_SNIPPET \n"
84+ mkdir -p $RESOURCES_TOP_DIR
8085 cat << EOF > $VENV_BASH_SNIPPET
8186# Add "source $VENV_BASH_SNIPPET " to your ~/.bashrc to activate
8287# the Pimoroni virtual environment automagically!
@@ -96,23 +101,32 @@ venv_check() {
96101 PYTHON_BIN=` which $PYTHON `
97102 if [[ $VIRTUAL_ENV == " " ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV * ]]; then
98103 printf " This script should be run in a virtual Python environment.\n"
99- if confirm " Would you like us to create one for you?" ; then
104+ if confirm " Would you like us to create and/or use a default one?" ; then
105+ printf " \n"
100106 if [ ! -f $VENV_DIR /bin/activate ]; then
101- inform " Creating virtual Python environment in $VENV_DIR , please wait...\n"
107+ inform " Creating a new virtual Python environment in $VENV_DIR , please wait...\n"
102108 mkdir -p $VENV_DIR
103109 /usr/bin/python3 -m venv $VENV_DIR --system-site-packages
104110 venv_bash_snippet
111+ source $VENV_DIR /bin/activate
105112 else
106- inform " Found existing virtual Python environment in $VENV_DIR \n"
113+ inform " Activating existing virtual Python environment in $VENV_DIR \n"
114+ printf " source $VENV_DIR /bin/activate\n"
115+ source $VENV_DIR /bin/activate
107116 fi
108- inform " Activating virtual Python environment in $VENV_DIR ..."
109- inform " source $VENV_DIR /bin/activate\n"
110- source $VENV_DIR /bin/activate
111-
112117 else
113- exit 1
118+ printf " \n"
119+ fatal " Please create and/or activate a virtual Python environment and try again!\n"
114120 fi
115121 fi
122+ printf " \n"
123+ }
124+
125+ check_for_error () {
126+ if [ $? -ne 0 ]; then
127+ CMD_ERRORS=true
128+ warning " ^^^ 😬"
129+ fi
116130}
117131
118132function do_config_backup {
@@ -132,6 +146,7 @@ function do_config_backup {
132146function apt_pkg_install {
133147 PACKAGES=()
134148 PACKAGES_IN=(" $@ " )
149+ # Check the list of packages and only run update/install if we need to
135150 for (( i = 0 ; i < ${# PACKAGES_IN[@]} ; i++ )) ; do
136151 PACKAGE=" ${PACKAGES_IN[$i]} "
137152 if [ " $PACKAGE " == " " ]; then continue ; fi
@@ -143,20 +158,24 @@ function apt_pkg_install {
143158 done
144159 PACKAGES=" ${PACKAGES[@]} "
145160 if ! [ " $PACKAGES " == " " ]; then
146- echo " Installing missing packages: $PACKAGES "
161+ printf " \n"
162+ inform " Installing missing packages: $PACKAGES "
147163 if [ ! $APT_HAS_UPDATED ]; then
148164 sudo apt update
149165 APT_HAS_UPDATED=true
150166 fi
151167 sudo apt install -y $PACKAGES
168+ check_for_error
152169 if [ -f " $UNINSTALLER " ]; then
153170 echo " apt uninstall -y $PACKAGES " >> $UNINSTALLER
154171 fi
155172 fi
156173}
157174
158175function pip_pkg_install {
176+ # A null Keyring prevents pip stalling in the background
159177 PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring $PYTHON -m pip install --upgrade " $@ "
178+ check_for_error
160179}
161180
162181while [[ $# -gt 0 ]]; do
@@ -186,30 +205,33 @@ while [[ $# -gt 0 ]]; do
186205 esac
187206done
188207
208+ printf " Installing $LIBRARY_NAME ...\n\n"
209+
189210user_check
190211venv_check
191212
192213if [ ! -f ` which $PYTHON ` ]; then
193- printf " Python path $PYTHON not found!\n"
194- exit 1
214+ fatal " Python path $PYTHON not found!\n"
195215fi
196216
197217PYTHON_VER=` $PYTHON --version`
198218
199- printf " $LIBRARY_NAME Python Library: Installer\n\n"
200-
201219inform " Checking Dependencies. Please wait..."
202220
221+ # Install toml and try to read pyproject.toml into bash variables
222+
203223pip_pkg_install toml
204224
205225CONFIG_VARS=` $PYTHON - << EOF
206226import toml
207227config = toml.load("pyproject.toml")
228+ github_url = config['project']['urls']['GitHub']
208229p = dict(config['tool']['pimoroni'])
209230# Convert list config entries into bash arrays
210231for k, v in p.items():
211232 v = "'\n\t'".join(v)
212233 p[k] = f"('{v}')"
234+ print(f'GITHUB_URL="{github_url}"')
213235print("""
214236APT_PACKAGES={apt_packages}
215237SETUP_CMDS={commands}
@@ -218,8 +240,8 @@ CONFIG_TXT={configtxt}
218240EOF`
219241
220242if [ $? -ne 0 ]; then
221- warning " Error parsing configuration...\n "
222- exit 1
243+ # This is bad, this should not happen in production!
244+ fatal " Error parsing configuration...\n "
223245fi
224246
225247eval $CONFIG_VARS
@@ -229,13 +251,17 @@ UNINSTALLER=$RESOURCES_DIR/uninstall.sh
229251
230252RES_DIR_OWNER=` stat -c "%U" $RESOURCES_TOP_DIR `
231253
254+ # Previous install.sh scripts were run as root with sudo, which caused
255+ # the ~/Pimoroni dir to be created with root ownership. Try and fix it.
232256if [[ " $RES_DIR_OWNER " == " root" ]]; then
233257 warning " \n\nFixing $RESOURCES_TOP_DIR permissions!\n\n"
234258 sudo chown -R $USER :$USER $RESOURCES_TOP_DIR
235259fi
236260
237261mkdir -p $RESOURCES_DIR
238262
263+ # Create a stub uninstaller file, we'll try to add the inverse of every
264+ # install command run to here, though it's not complete.
239265cat << EOF > $UNINSTALLER
240266printf "It's recommended you run these steps manually.\n"
241267printf "If you want to run the full script, open it in\n"
@@ -244,19 +270,23 @@ exit 1
244270source $VIRTUAL_ENV /bin/activate
245271EOF
246272
247- if $UNSTABLE ; then
248- warning " Installing unstable library from source.\n\n"
249- else
250- printf " Installing stable library from pypi.\n\n"
251- fi
273+ printf " \n"
252274
253275inform " Installing for $PYTHON_VER ...\n"
276+
277+ # Install apt packages from pyproject.toml / tool.pimoroni.apt_packages
254278apt_pkg_install " ${APT_PACKAGES[@]} "
279+
280+ printf " \n"
281+
255282if $UNSTABLE ; then
283+ warning " Installing unstable library from source.\n"
256284 pip_pkg_install .
257285else
286+ inform " Installing stable library from pypi.\n"
258287 pip_pkg_install $LIBRARY_NAME
259288fi
289+
260290if [ $? -eq 0 ]; then
261291 success " Done!\n"
262292 echo " $PYTHON -m pip uninstall $LIBRARY_NAME " >> $UNINSTALLER
@@ -266,27 +296,38 @@ cd $WD
266296
267297find_config
268298
299+ # Run the setup commands from pyproject.toml / tool.pimoroni.commands
300+
269301for (( i = 0 ; i < ${# SETUP_CMDS[@]} ; i++ )) ; do
270302 CMD=" ${SETUP_CMDS[$i]} "
271303 # Attempt to catch anything that touches config.txt and trigger a backup
272304 if [[ " $CMD " == * " raspi-config" * ]] || [[ " $CMD " == * " $CONFIG_DIR /$CONFIG_FILE " * ]] || [[ " $CMD " == * " \$ CONFIG_DIR/\$ CONFIG_FILE" * ]]; then
273305 do_config_backup
274306 fi
275307 eval $CMD
308+ check_for_error
276309done
277310
311+ printf " \n"
312+
313+ # Add the config.txt entries from pyproject.toml / tool.pimoroni.configtxt
314+
278315for (( i = 0 ; i < ${# CONFIG_TXT[@]} ; i++ )) ; do
279316 CONFIG_LINE=" ${CONFIG_TXT[$i]} "
280317 if ! [ " $CONFIG_LINE " == " " ]; then
281318 do_config_backup
282- inform " Adding $CONFIG_LINE to $CONFIG_DIR /$CONFIG_FILE \n "
319+ inform " Adding $CONFIG_LINE to $CONFIG_DIR /$CONFIG_FILE "
283320 sudo sed -i " s/^#$CONFIG_LINE /$CONFIG_LINE /" $CONFIG_DIR /$CONFIG_FILE
284321 if ! grep -q " ^$CONFIG_LINE " $CONFIG_DIR /$CONFIG_FILE ; then
285322 printf " $CONFIG_LINE \n" | sudo tee --append $CONFIG_DIR /$CONFIG_FILE
286323 fi
287324 fi
288325done
289326
327+ printf " \n"
328+
329+ # Just a straight copy of the examples/ dir into ~/Pimoroni/board/examples
330+
290331if [ -d " examples" ]; then
291332 if confirm " Would you like to copy examples to $RESOURCES_DIR ?" ; then
292333 inform " Copying examples to $RESOURCES_DIR "
298339
299340printf " \n"
300341
342+ # Use pdoc to generate basic documentation from the installed module
343+
301344if confirm " Would you like to generate documentation?" ; then
345+ inform " Installing pdoc. Please wait..."
302346 pip_pkg_install pdoc
303- printf " Generating documentation.\n"
347+ inform " Generating documentation.\n"
304348 $PYTHON -m pdoc $LIBRARY_NAME -o $RESOURCES_DIR /docs > /dev/null
305349 if [ $? -eq 0 ]; then
306350 inform " Documentation saved to $RESOURCES_DIR /docs"
@@ -310,6 +354,22 @@ if confirm "Would you like to generate documentation?"; then
310354 fi
311355fi
312356
313- success " \nAll done!"
314- inform " If this is your first time installing you should reboot for hardware changes to take effect.\n"
315- inform " Find uninstall steps in $UNINSTALLER \n"
357+ printf " \n"
358+
359+ if [ " $CMD_ERRORS " = true ]; then
360+ warning " One or more setup commands appear to have failed."
361+ printf " This might prevent things from working properly.\n"
362+ printf " Make sure your OS is up to date and try re-running this installer.\n"
363+ printf " If things still don't work, report this or find help at $GITHUB_URL .\n\n"
364+ else
365+ success " \nAll done!"
366+ fi
367+
368+ printf " If this is your first time installing you should reboot for hardware changes to take effect.\n"
369+ printf " Find uninstall steps in $UNINSTALLER \n\n"
370+
371+ if [ " $CMD_ERRORS " = true ]; then
372+ exit 1
373+ else
374+ exit 0
375+ fi
0 commit comments