Sync with boilerplate.

This commit is contained in:
Phil Howard
2024-01-11 12:41:41 +00:00
parent 7513fde92a
commit e72e9bf6a5
3 changed files with 139 additions and 82 deletions

View File

@@ -3,9 +3,9 @@
# This script handles some basic QA checks on the source
NOPOST=$1
LIBRARY_NAME=`hatch project metadata name`
LIBRARY_VERSION=`hatch version | awk -F "." '{print $1"."$2"."$3}'`
POST_VERSION=`hatch version | awk -F "." '{print substr($4,0,length($4))}'`
LIBRARY_NAME=$(hatch project metadata name)
LIBRARY_VERSION=$(hatch version | awk -F "." '{print $1"."$2"."$3}')
POST_VERSION=$(hatch version | awk -F "." '{print substr($4,0,length($4))}')
TERM=${TERM:="xterm-256color"}
success() {
@@ -29,7 +29,7 @@ while [[ $# -gt 0 ]]; do
;;
*)
if [[ $1 == -* ]]; then
printf "Unrecognised option: $1\n";
printf "Unrecognised option: %s\n" "$1";
exit 1
fi
POSITIONAL_ARGS+=("$1")
@@ -40,8 +40,7 @@ done
inform "Checking $LIBRARY_NAME $LIBRARY_VERSION\n"
inform "Checking for trailing whitespace..."
grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO
if [[ $? -eq 0 ]]; then
if grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO; then
warning "Trailing whitespace found!"
exit 1
else
@@ -50,8 +49,7 @@ fi
printf "\n"
inform "Checking for DOS line-endings..."
grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile
if [[ $? -eq 0 ]]; then
if grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile; then
warning "DOS line-endings found!"
exit 1
else
@@ -60,8 +58,7 @@ fi
printf "\n"
inform "Checking CHANGELOG.md..."
cat CHANGELOG.md | grep ^${LIBRARY_VERSION} > /dev/null 2>&1
if [[ $? -eq 1 ]]; then
if ! grep "^${LIBRARY_VERSION}" CHANGELOG.md > /dev/null 2>&1; then
warning "Changes missing for version ${LIBRARY_VERSION}! Please update CHANGELOG.md."
exit 1
else
@@ -70,8 +67,7 @@ fi
printf "\n"
inform "Checking for git tag ${LIBRARY_VERSION}..."
git tag -l | grep -E "${LIBRARY_VERSION}$"
if [[ $? -eq 1 ]]; then
if ! git tag -l | grep -E "${LIBRARY_VERSION}$"; then
warning "Missing git tag for version ${LIBRARY_VERSION}"
fi
printf "\n"

View File

@@ -6,21 +6,20 @@ CONFIG_DIR="/boot/firmware"
DATESTAMP=$(date "+%Y-%m-%d-%H-%M-%S")
CONFIG_BACKUP=false
APT_HAS_UPDATED=false
RESOURCES_TOP_DIR=$HOME/Pimoroni
VENV_BASH_SNIPPET=$RESOURCES_DIR/auto_venv.sh
VENV_DIR=$HOME/.virtualenvs/pimoroni
WD=$(pwd)
RESOURCES_TOP_DIR="$HOME/Pimoroni"
VENV_BASH_SNIPPET="$RESOURCES_TOP_DIR/auto_venv.sh"
VENV_DIR="$HOME/.virtualenvs/pimoroni"
USAGE="./install.sh (--unstable)"
POSITIONAL_ARGS=()
FORCE=false
UNSTABLE=false
PYTHON="python"
CMD_ERRORS=false
user_check() {
if [ "$(id -u)" -eq 0 ]; then
printf "Script should not be run as root. Try './install.sh'\n"
exit 1
fatal "Script should not be run as root. Try './install.sh'\n"
fi
}
@@ -37,15 +36,6 @@ confirm() {
fi
}
prompt() {
read -r -p "$1 [y/N] " response < /dev/tty
if [[ $response =~ ^(yes|y|Y)$ ]]; then
true
else
false
fi
}
success() {
echo -e "$(tput setaf 2)$1$(tput sgr0)"
}
@@ -55,29 +45,36 @@ inform() {
}
warning() {
echo -e "$(tput setaf 1)$1$(tput sgr0)"
echo -e "$(tput setaf 1)⚠ WARNING:$(tput sgr0) $1"
}
fatal() {
echo -e "$(tput setaf 1)⚠ FATAL:$(tput sgr0) $1"
exit 1
}
find_config() {
if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then
CONFIG_DIR="/boot"
if [ ! -f "$CONFIG_DIR/$CONFIG_FILE" ]; then
warning "Could not find $CONFIG_FILE!"
exit 1
fatal "Could not find $CONFIG_FILE!"
fi
else
if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then
warning "Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR/$CONFIG_FILE"
warning "You might want to fix this!"
fi
else
if [ -f "/boot/$CONFIG_FILE" ] && [ ! -L "/boot/$CONFIG_FILE" ]; then
warning "Oops! It looks like /boot/$CONFIG_FILE is not a link to $CONFIG_DIR/$CONFIG_FILE"
warning "You might want to fix this!"
fi
fi
inform "Using $CONFIG_FILE in $CONFIG_DIR"
inform "Using $CONFIG_FILE in $CONFIG_DIR"
}
venv_bash_snippet() {
inform "Checking for $VENV_BASH_SNIPPET\n"
if [ ! -f "$VENV_BASH_SNIPPET" ]; then
inform "Creating $VENV_BASH_SNIPPET\n"
mkdir -p "$RESOURCES_TOP_DIR"
cat << EOF > "$VENV_BASH_SNIPPET"
# Add `source $RESOURCES_DIR/auto_venv.sh` to your ~/.bashrc to activate
# Add "source $VENV_BASH_SNIPPET" to your ~/.bashrc to activate
# the Pimoroni virtual environment automagically!
VENV_DIR="$VENV_DIR"
if [ ! -f \$VENV_DIR/bin/activate ]; then
@@ -95,23 +92,34 @@ venv_check() {
PYTHON_BIN=$(which "$PYTHON")
if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then
printf "This script should be run in a virtual Python environment.\n"
if confirm "Would you like us to create one for you?"; then
if confirm "Would you like us to create and/or use a default one?"; then
printf "\n"
if [ ! -f "$VENV_DIR/bin/activate" ]; then
inform "Creating virtual Python environment in $VENV_DIR, please wait...\n"
inform "Creating a new virtual Python environment in $VENV_DIR, please wait...\n"
mkdir -p "$VENV_DIR"
/usr/bin/python3 -m venv "$VENV_DIR" --system-site-packages
venv_bash_snippet
# shellcheck disable=SC1091
source "$VENV_DIR/bin/activate"
else
inform "Found existing virtual Python environment in $VENV_DIR\n"
inform "Activating existing virtual Python environment in $VENV_DIR\n"
printf "source \"%s/bin/activate\"\n" "$VENV_DIR"
# shellcheck disable=SC1091
source "$VENV_DIR/bin/activate"
fi
inform "Activating virtual Python environment in $VENV_DIR..."
inform "source $VENV_DIR/bin/activate\n"
source "$VENV_DIR/bin/activate"
else
exit 1
printf "\n"
fatal "Please create and/or activate a virtual Python environment and try again!\n"
fi
fi
printf "\n"
}
check_for_error() {
if [ $? -ne 0 ]; then
CMD_ERRORS=true
warning "^^^ 😬 previous command did not exit cleanly!"
fi
}
function do_config_backup {
@@ -119,7 +127,7 @@ function do_config_backup {
CONFIG_BACKUP=true
FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt"
inform "Backing up $CONFIG_DIR/$CONFIG_FILE to $CONFIG_DIR/$FILENAME\n"
sudo cp "$CONFIG_DIR/$CONFIG_FILE $CONFIG_DIR/$FILENAME"
sudo cp "$CONFIG_DIR/$CONFIG_FILE" "$CONFIG_DIR/$FILENAME"
mkdir -p "$RESOURCES_TOP_DIR/config-backups/"
cp $CONFIG_DIR/$CONFIG_FILE "$RESOURCES_TOP_DIR/config-backups/$FILENAME"
if [ -f "$UNINSTALLER" ]; then
@@ -129,25 +137,28 @@ function do_config_backup {
}
function apt_pkg_install {
PACKAGES=()
PACKAGES_NEEDED=()
PACKAGES_IN=("$@")
# Check the list of packages and only run update/install if we need to
for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do
PACKAGE="${PACKAGES_IN[$i]}"
if [ "$PACKAGE" == "" ]; then continue; fi
printf "Checking for %s\n" "$PACKAGE"
dpkg -L "$PACKAGE" > /dev/null 2>&1
if [ "$?" == "1" ]; then
PACKAGES+=("$PACKAGE")
PACKAGES_NEEDED+=("$PACKAGE")
fi
done
PACKAGES="${PACKAGES[@]}"
PACKAGES="${PACKAGES_NEEDED[*]}"
if ! [ "$PACKAGES" == "" ]; then
echo "Installing missing packages: $PACKAGES"
printf "\n"
inform "Installing missing packages: $PACKAGES"
if [ ! $APT_HAS_UPDATED ]; then
sudo apt update
APT_HAS_UPDATED=true
fi
sudo apt install -y $PACKAGES
sudo apt install -y "$PACKAGES"
check_for_error
if [ -f "$UNINSTALLER" ]; then
echo "apt uninstall -y $PACKAGES" >> "$UNINSTALLER"
fi
@@ -155,7 +166,9 @@ function apt_pkg_install {
}
function pip_pkg_install {
# A null Keyring prevents pip stalling in the background
PYTHON_KEYRING_BACKEND=keyring.backends.null.Keyring $PYTHON -m pip install --upgrade "$@"
check_for_error
}
while [[ $# -gt 0 ]]; do
@@ -185,40 +198,46 @@ while [[ $# -gt 0 ]]; do
esac
done
printf "Installing %s...\n\n" "$LIBRARY_NAME"
user_check
venv_check
if [ ! -f "$(which $PYTHON)" ]; then
printf "Python path %s not found!\n" "$PYTHON"
exit 1
if [ ! -f "$(which "$PYTHON")" ]; then
fatal "Python path %s not found!\n" "$PYTHON"
fi
PYTHON_VER=$($PYTHON --version)
printf "%s Python Library: Installer\n\n" $LIBRARY_NAME
inform "Checking Dependencies. Please wait..."
# Install toml and try to read pyproject.toml into bash variables
pip_pkg_install toml
CONFIG_VARS=`$PYTHON - <<EOF
CONFIG_VARS=$(
$PYTHON - <<EOF
import toml
config = toml.load("pyproject.toml")
github_url = config['project']['urls']['GitHub']
p = dict(config['tool']['pimoroni'])
# Convert list config entries into bash arrays
for k, v in p.items():
v = "'\n\t'".join(v)
p[k] = f"('{v}')"
print(f'GITHUB_URL="{github_url}"')
print("""
APT_PACKAGES={apt_packages}
SETUP_CMDS={commands}
CONFIG_TXT={configtxt}
""".format(**p))
EOF`
EOF
)
# shellcheck disable=SC2181 # Inlining the above command would be messy
if [ $? -ne 0 ]; then
warning "Error parsing configuration...\n"
exit 1
# This is bad, this should not happen in production!
fatal "Error parsing configuration...\n"
fi
eval "$CONFIG_VARS"
@@ -228,6 +247,8 @@ UNINSTALLER=$RESOURCES_DIR/uninstall.sh
RES_DIR_OWNER=$(stat -c "%U" "$RESOURCES_TOP_DIR")
# Previous install.sh scripts were run as root with sudo, which caused
# the ~/Pimoroni dir to be created with root ownership. Try and fix it.
if [[ "$RES_DIR_OWNER" == "root" ]]; then
warning "\n\nFixing $RESOURCES_TOP_DIR permissions!\n\n"
sudo chown -R "$USER:$USER" "$RESOURCES_TOP_DIR"
@@ -235,6 +256,8 @@ fi
mkdir -p "$RESOURCES_DIR"
# Create a stub uninstaller file, we'll try to add the inverse of every
# install command run to here, though it's not complete.
cat << EOF > "$UNINSTALLER"
printf "It's recommended you run these steps manually.\n"
printf "If you want to run the full script, open it in\n"
@@ -243,49 +266,69 @@ exit 1
source $VIRTUAL_ENV/bin/activate
EOF
if $UNSTABLE; then
warning "Installing unstable library from source.\n\n"
else
printf "Installing stable library from pypi.\n\n"
fi
printf "\n"
inform "Installing for $PYTHON_VER...\n"
# Install apt packages from pyproject.toml / tool.pimoroni.apt_packages
apt_pkg_install "${APT_PACKAGES[@]}"
printf "\n"
if $UNSTABLE; then
warning "Installing unstable library from source.\n"
pip_pkg_install .
else
inform "Installing stable library from pypi.\n"
pip_pkg_install "$LIBRARY_NAME"
fi
# shellcheck disable=SC2181 # One of two commands run, depending on --unstable flag
if [ $? -eq 0 ]; then
success "Done!\n"
echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> "$UNINSTALLER"
fi
cd "$WD" || exit 1
find_config
printf "\n"
# Run the setup commands from pyproject.toml / tool.pimoroni.commands
inform "Running setup commands...\n"
for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do
CMD="${SETUP_CMDS[$i]}"
# Attempt to catch anything that touches config.txt and trigger a backup
if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG_DIR/$CONFIG_FILE"* ]] || [[ "$CMD" == *"\$CONFIG_DIR/\$CONFIG_FILE"* ]]; then
do_config_backup
fi
if [[ ! "$CMD" == printf* ]]; then
printf "Running: \"%s\"\n" "$CMD"
fi
eval "$CMD"
check_for_error
done
printf "\n"
# Add the config.txt entries from pyproject.toml / tool.pimoroni.configtxt
for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do
CONFIG_LINE="${CONFIG_TXT[$i]}"
if ! [ "$CONFIG_LINE" == "" ]; then
do_config_backup
inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE\n"
inform "Adding $CONFIG_LINE to $CONFIG_DIR/$CONFIG_FILE"
sudo sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG_DIR/$CONFIG_FILE
if ! grep -q "^$CONFIG_LINE" $CONFIG_DIR/$CONFIG_FILE; then
printf "%s\n" "$CONFIG_LINE" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE
printf "%s \n" "$CONFIG_LINE" | sudo tee --append $CONFIG_DIR/$CONFIG_FILE
fi
fi
done
printf "\n"
# Just a straight copy of the examples/ dir into ~/Pimoroni/board/examples
if [ -d "examples" ]; then
if confirm "Would you like to copy examples to $RESOURCES_DIR?"; then
inform "Copying examples to $RESOURCES_DIR"
@@ -297,11 +340,13 @@ fi
printf "\n"
# Use pdoc to generate basic documentation from the installed module
if confirm "Would you like to generate documentation?"; then
inform "Installing pdoc. Please wait..."
pip_pkg_install pdoc
printf "Generating documentation.\n"
$PYTHON -m pdoc $MODULE_NAME -o "$RESOURCES_DIR/docs" > /dev/null
if [ $? -eq 0 ]; then
inform "Generating documentation.\n"
if $PYTHON -m pdoc "$MODULE_NAME" -o "$RESOURCES_DIR/docs" > /dev/null; then
inform "Documentation saved to $RESOURCES_DIR/docs"
success "Done!"
else
@@ -309,6 +354,22 @@ if confirm "Would you like to generate documentation?"; then
fi
fi
success "\nAll done!"
inform "If this is your first time installing you should reboot for hardware changes to take effect.\n"
inform "Find uninstall steps in $UNINSTALLER\n"
printf "\n"
if [ "$CMD_ERRORS" = true ]; then
warning "One or more setup commands appear to have failed."
printf "This might prevent things from working properly.\n"
printf "Make sure your OS is up to date and try re-running this installer.\n"
printf "If things still don't work, report this or find help at %s.\n\n" "$GITHUB_URL"
else
success "\nAll done!"
fi
printf "If this is your first time installing you should reboot for hardware changes to take effect.\n"
printf "Find uninstall steps in %s\n\n" "$UNINSTALLER"
if [ "$CMD_ERRORS" = true ]; then
exit 1
else
exit 0
fi

View File

@@ -1,13 +1,13 @@
#!/bin/bash
FORCE=false
LIBRARY_NAME=`grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}'`
LIBRARY_NAME=$(grep -m 1 name pyproject.toml | awk -F" = " '{print substr($2,2,length($2)-2)}')
RESOURCES_DIR=$HOME/Pimoroni/$LIBRARY_NAME
PYTHON="python"
venv_check() {
PYTHON_BIN=`which $PYTHON`
PYTHON_BIN=$(which $PYTHON)
if [[ $VIRTUAL_ENV == "" ]] || [[ $PYTHON_BIN != $VIRTUAL_ENV* ]]; then
printf "This script should be run in a virtual Python environment.\n"
exit 1
@@ -15,7 +15,7 @@ venv_check() {
}
user_check() {
if [ $(id -u) -eq 0 ]; then
if [ "$(id -u)" -eq 0 ]; then
printf "Script should not be run as root. Try './uninstall.sh'\n"
exit 1
fi
@@ -55,17 +55,17 @@ warning() {
echo -e "$(tput setaf 1)$1$(tput sgr0)"
}
printf "$LIBRARY_NAME Python Library: Uninstaller\n\n"
printf "%s Python Library: Uninstaller\n\n" "$LIBRARY_NAME"
user_check
venv_check
printf "Uninstalling for Python 3...\n"
$PYTHON -m pip uninstall $LIBRARY_NAME
$PYTHON -m pip uninstall "$LIBRARY_NAME"
if [ -d $RESOURCES_DIR ]; then
if [ -d "$RESOURCES_DIR" ]; then
if confirm "Would you like to delete $RESOURCES_DIR?"; then
rm -r $RESOURCES_DIR
rm -r "$RESOURCES_DIR"
fi
fi