#!/bin/sh export SHELL_NAME="$(ps -p $$ -o comm=)" export NANDBASE_GIT='https://github.com/doubleo-dev/nand-base.git' export NANDBASE_ROOT="$HOME/nand-base" export CONDA_INSTALLER_PATH="$NANDBASE_ROOT/Anaconda3-Linux-x86_64.sh" export CONDA_PAGE_URL='https://www.anaconda.com/download/success' export CONDA_LATEST_URL_REGEX='https://repo.anaconda.com/archive/Anaconda3-[^"]*-Linux-x86_64.sh' export FLAG_DEPS_COMMON="$NANDBASE_ROOT/.deps-installed" get_select() { # Prompt for input in a Linux shell script # https://stackoverflow.com/a/226724 __prompt="$1" while true; do echo -n "$__prompt ('yes' or 'no') : " read __answer case "$__answer" in [YyTt1]* ) return 1; ;; # yes, true [NnFf0]* ) return 0; ;; # no, false * ) echo "ERROR: Please answer 'yes' or 'no'.";; esac done } is_sourced() { # Detect if a script is being sourced # https://stackoverflow.com/a/28776166 if [ -n "$ZSH_VERSION" ]; then case "$ZSH_EVAL_CONTEXT" in *:file:*) return 0;; esac # sourced else # add additional POSIX-compatible shell names here, if needed case "${0##*/}" in dash|-dash|bash|-bash|ksh|-ksh|sh|-sh) return 0;; esac # sourced fi return 1 # not sourced } count_missing_submodules() { __count=0 while read -r __line; do case "$__line" in -*) __count=$((__count + 1));; esac done echo "$__count" # stdout the number of missing submodules return $__count } conda_find_env() { __env_name="$1" if conda env list 2> /dev/null | awk '{print $1}' | grep -x "$__env_name" > /dev/null; then return 0 # success else return 1 # failure fi } conda_get_latest_url() { # stdout the url curl "$CONDA_PAGE_URL" 2>/dev/null | grep -o '' | head -n1 return $? } conda_download_latest() { __conda_url="$1" __conda_installer="$2" curl -L "$__conda_url" -o "$__conda_installer" return $? } check_deps() { if ! is_sourced; then echo 'ERROR: The script was executed directly, not sourced. Please run using "source" or "." (a single dot).' echo '' echo " expected: source $0" echo " . $0" echo " got: $0 $@" echo '' echo " hint: . $0 (Note the leading dot and the required space)" echo '' return 11 fi __real_script_path="$(dirname "$(realpath "$0")")" __expected_script_path="$NANDBASE_ROOT/bin" if [ "$__real_script_path" != "$__expected_script_path" ]; then echo 'ERROR: The script was executed in incorrect path. Please run at the expected path.' echo '' echo " expected: $__expected_script_path" echo " got: $__real_script_path" echo '' echo " hint: . $_expected_script_path" echo '' echo ' note: To run the script anywhere, add following line to your shell rc file:' echo '' echo " echo PATH=\"$NANDBASE_ROOT/bin:$PATH\" > ~/.${SHELL_NAME}rc" echo '' get_select 'PROMPT: If you did not clone the NAND flash development base yet, do you want to download?' if [ $? -eq 0 ]; then return 12 fi git clone --recursive "$NANDBASE_GIT" "$NANDBASE_ROOT" if [ $? -ne 0 ]; then echo 'ERROR: Failed to clone the NAND flash development base. Please clone it with Git manually.' echo '' echo " hint: git clone --recursive $NANDBASE_GIT $NANDBASE_ROOT" echo '' return 13 fi echo 'INFO: NAND flash development base has been downloaded.' echo ' Please re-run the script.' echo '' echo " hint: . $_expected_script_path" return 14 fi if [ ! -f "$FLAG_DEPS_COMMON" ]; then get_select 'PROMPT: The common dependencies not installed. Install now?' if [ $? -eq 0 ]; then echo 'ERROR: The common dependencies not installed.' echo '' echo " expected: $FLAG_DEPS_COMMON" echo ' got: (flag file does not exist at the expected path)' echo '' echo ' hint: sudo apt install git' echo " touch $FLAG_DEPS_COMMON" echo '' return 15 fi sudo apt install git if [ $? -ne 0 ]; then echo 'ERROR: An error occurred during installing the dependencies.' echo '' echo ' hint: sudo apt install git' echo " touch $FLAG_DEPS_COMMON" echo '' return 16 fi touch $FLAG_DEPS_COMMON if [ $? -ne 0 ]; then echo 'WARNING: Cannot access to the flag file. You should touch it manually.' echo '' echo " hint: touch $FLAG_DEPS_COMMON" echo '' fi fi __expected_git_path="$NANDBASE_ROOT/.git" if [ ! -d "$__real_git_path" ]; then get_select 'PROMPT: The NAND flash development base is missing. Download now?' if [ $? -eq 0 ]; then echo 'ERROR: The NAND flash development base is missing. Please clone it with Git.' echo '' echo " expected: $__expected_git_path" echo ' got: (directory does not exist at the expected path)' echo '' echo " hint: git clone --recursive $NANDBASE_GIT $NANDBASE_ROOT" echo '' return 12 fi git clone --recursive "$NANDBASE_GIT" "$NANDBASE_ROOT" if [ $? -ne 0 ]; then echo 'ERROR: Failed to clone the NAND flash development base. Please clone it with Git manually.' echo '' echo " hint: git clone --recursive $NANDBASE_GIT $NANDBASE_ROOT" echo '' return 13 fi echo 'INFO: NAND flash development base downloaded completed.' fi which conda > /dev/null 2>&1 if [ $? -ne 0 ]; then get_select "PROMPT: Anaconda is missing. Download now?" if [ $? -eq 0 ]; then echo 'ERROR: Anaconda is not installed. Please install it.' echo '' echo " hint: 1. Visit $CONDA_PAGE_URL" echo ' 2. Open "Distribution Installers"' echo ' 3. Download "Linux 64-Bit (x86) Installer"' echo ' 4. Open a terminal and run the following commands:' echo '' echo ' chmod +x Anaconda3-$VERSION-Linux-x86_64.sh' echo ' ./Anaconda3-$VERSION-Linux-x86_64.sh' echo '' echo ' 5. Follow the installer prompts. Enable shell integration when prompted.' echo ' 6. Restart the terminal.' echo '' return 13 fi __conda_installer="$CONDA_INSTALLER_PATH" __conda_url="$(conda_get_latest_url)" __retcode=$? if [ $__retcode -eq 0 ]; then echo "INFO: Downloading Anaconda installer from $__conda_url" conda_download_latest "$__conda_url" "$__conda_installer" __retcode=$? fi if [ $__retcode -ne 0 ]; then echo 'ERROR: Failed to download Anaconda. Please download manually.' echo '' echo ' hint: 1. Check your Internet connection.' echo " 2. Visit $CONDA_PAGE_URL" echo ' 3. Open "Distribution Installers"' echo ' 4. Download "Linux 64-Bit (x86) Installer"' echo ' 5. Open a terminal and run the following commands:' echo '' echo ' chmod +x Anaconda3-$VERSION-Linux-x86_64.sh' echo ' ./Anaconda3-$VERSION-Linux-x86_64.sh' echo '' echo ' 6. Follow the installer prompts. Enable shell integration when prompted.' echo ' 7. Restart the terminal.' echo '' return 14 fi echo "INFO: Anaconda installer downloaded to $__conda_installer" echo 'INFO: Running Anaconda installer. Please follow the prompts. Enable shell integration when prompted.' chmod +x "$__conda_installer" "$__conda_installer" if [ $? -ne 0 ]; then echo 'ERROR: Anaconda installation failed.' echo '' echo ' hint: Check the error messages above.' echo '' return 15 fi echo 'INFO: Anaconda installation completed.' fi return 0 } check_deps_riot() { if [ ! -d "$RIOTBASE" ]; then get_select 'PROMPT: RIOT OS base submodule is missing. Download now?' if [ $? -eq 0 ]; then echo 'ERROR: Failed to load the RIOT OS base submodule.' echo '' echo " expected: $RIOTBASE" echo ' got: (directory does not exist at the expected path)' echo '' echo " hint: cd $NANDBASE_ROOT" echo ' git submodule update --init --recursive' echo '' return 31 fi pushd "$NANDBASE_ROOT" git submodule update --init --recursive __retcode=$? popd if [ $__retcode -ne 0 ]; then echo 'ERROR: An error occurred while downloading the RIOT OS.' echo '' echo " hint: cd $NANDBASE_ROOT" echo ' git submodule update --init --recursive' echo '' return 32 fi echo 'INFO: RIOT OS download completed.' fi if [ ! -d "$IDF_PATH" ]; then get_select 'PROMPT: RIOT OS patched ESP-IDF is not installed. Install?' if [ $? -eq 0 ]; then echo 'ERROR: RIOT OS patched ESP-IDF is not installed properly.' echo '' echo " expected: $IDF_PATH" echo ' got: (directory does not exist at the expected path)' echo '' echo " hint: cd $IDF_PATH" echo ' git submodule update --init --recursive' echo '' return 33 fi make -f ~/nand-base/riot/esp-idf.Makefile if [ $? -ne 0 ]; then echo 'ERROR: An error occurred during installing RIOT OS patched ESP-IDF.' return 34 fi echo 'INFO: RIOT OS patched ESP-IDF installation completed.' fi pushd "$IDF_PATH" > /dev/null 2>&1 __missing_submodules_count="$(git submodule status | count_missing_submodules)" popd > /dev/null 2>&1 if [ "$__missing_submodules_count" != "0" ]; then get_select 'PROMPT: RIOT OS patched ESP-IDF submodules not loaded. Download now?' if [ $? -eq 0 ]; then echo 'ERROR: RIOT OS patched ESP-IDF submodules not loaded properly.' echo '' echo ' expected: 0' echo " got: $__missing_submodules_count (number of missing submodules)" echo '' echo ' hint: cd ~/nand-base/riot/esp-idf' echo ' git submodule update --init --recursive' echo '' return 35 fi pushd ~/nand-base/riot/esp-idf git submodule update --init --recursive __retcode=$? popd if [ $__retcode -ne 0 ]; then echo 'ERROR: An error occurred during downloading the RIOT OS patched ESP-IDF submodules.' return 36 fi echo "INFO: RIOT OS patched ESP-IDF submodules have been loaded." fi conda_find_env "$CONDA_ENV_NAME" if [ $? -ne 0 ]; then get_select "PROMPT: Anaconda environment '$CONDA_ENV_NAME' not created. Create?" if [ $? -eq 0 ]; then echo 'ERROR: Anaconda environment '$CONDA_ENV_NAME' not created. Please create the environment.' echo '' echo " hint: conda create -n $CONDA_ENV_NAME python=3.8" echo " conda activate $CONDA_ENV_NAME" echo ' pip install psutil' echo '' return 37 fi conda create -n "$CONDA_ENV_NAME" python=3.8 if [ $? -ne 0 ]; then echo "ERROR: Anaconda environment '$CONDA_ENV_NAME' creation failed." echo '' echo ' hint: Check the error messages above.' echo ' You can create the environment manually:' echo '' echo " conda create -n $CONDA_ENV_NAME python=3.8" echo " conda activate $CONDA_ENV_NAME" echo ' pip install psutil' echo '' return 38 fi echo "INFO: Anaconda environment '$CONDA_ENV_NAME' has been created." pip install psutil if [ $? -ne 0 ]; then echo "WARNING: Python dependency 'psutil' installation failed." echo '' echo ' hint: Check the error messages above. You must install it manually:' echo '' echo " conda activate $CONDA_ENV_NAME" echo ' pip install psutil' echo '' echo ' note: This warning will not appear again.' echo ' Stopping here. After installing, re-run this script to continue.' echo '' return 39 fi fi __expected_idf_env_path="$IDF_TOOLS_PATH/idf-env.json" if [ ! -f "$__expected_idf_env_path" ]; then get_select "PROMPT: ESP32 tools are not installed. Install?" if [ $? -eq 0 ]; then echo 'ERROR: ESP32 tools are not installed properly.' echo '' echo " expected: $__expected_idf_env_path" echo ' got: (directory does not exist at the expected path)' echo '' echo " hint: export IDF_PATH=$IDF_PATH" echo " export IDF_TOOLS_PATH=$IDF_TOOLS_PATH" echo " conda activate '$CONDA_ENV_NAME'" echo ' cd ~/nand-base/riot/esp-idf' echo ' ./install.sh all' echo '' return 39 fi activate_conda || return $? pushd ~/nand-base/riot/esp-idf ./install.sh all __retcode=$? popd if [ $__retcode -ne 0 ]; then echo 'ERROR: An error occurred during installing the ESP32 tools.' return 40 fi echo "INFO: ESP32 tools installation completed." fi return 0 } check_deps_esp() { if [ ! -d "$IDF_PATH" ]; then get_select "PROMPT: ESP-IDF is not installed. Install?" if [ $? -eq 0 ]; then echo 'ERROR: ESP-IDF is not installed properly.' echo '' echo " expected: $IDF_PATH" echo ' got: (directory does not exist at the expected path)' echo '' echo ' hint: cd ~/nand-base' echo ' git submodule update --init --recursive' echo '' return 51 fi pushd ~/nand-base git submodule update --init --recursive __retcode=$? popd if [ $__retcode -ne 0 ]; then echo 'ERROR: An error occurred during installing the ESP-IDF.' return 52 fi echo "INFO: ESP-IDF installation completed." fi pushd "$IDF_PATH" > /dev/null 2>&1 __missing_submodules_count="$(git submodule status | count_missing_submodules)" popd > /dev/null 2>&1 if [ "$__missing_submodules_count" != "0" ]; then echo 'ERROR: ESP-IDF submodules not loaded properly.' echo '' echo ' expected: 0' echo " got: $__missing_submodules_count (number of missing submodules)" echo '' echo ' hint: cd ~/nand-base/esp/esp-idf' echo ' git submodule update --init --recursive' echo '' return 53 fi __expected_idf_env_path="$IDF_TOOLS_PATH/idf-env.json" if [ ! -f "$__expected_idf_env_path" ]; then get_select "PROMPT: ESP32 tools are not installed. Install?" if [ $? -eq 0 ]; then echo 'ERROR: ESP32 tools are not installed properly.' echo '' echo " expected: $__expected_idf_env_path" echo '' echo ' hint: cd ~/nand-base/esp/esp-idf' echo ' ./install.sh all' echo '' return 54 fi pushd ~/nand-base/esp/esp-idf activate_conda || return $? ./install.sh all __retcode=$? popd if [ $__retcode -ne 0 ]; then echo 'ERROR: An error occurred during installing the ESP-IDF.' return 55 fi echo "INFO: ESP-IDF installation completed." fi conda_find_env "$CONDA_ENV_NAME" if [ $? -ne 0 ]; then get_select "PROMPT: Anaconda environment '$CONDA_ENV_NAME' not created. Create?" if [ $? -eq 0 ]; then echo 'ERROR: Anaconda environment '$CONDA_ENV_NAME' not created. Please create the environment.' echo '' echo " hint: conda create -n $CONDA_ENV_NAME python=3.11" echo '' return 56 fi conda create -n "$CONDA_ENV_NAME" python=3.11 if [ $? -ne 0 ]; then echo "ERROR: Anaconda environment '$CONDA_ENV_NAME' creation failed." echo '' echo ' hint: Check the error messages above.' echo '' return 57 fi echo "INFO: Anaconda environment '$CONDA_ENV_NAME' has been created." fi return 0 } activate_conda() { __env_name="do-nand-$NANDBASE" eval "$(conda shell.$SHELL_NAME hook)" conda activate "$__env_name" if [ $? -ne 0 ]; then echo 'ERROR: Failed to activate Anaconda environment.' echo '' echo ' hint: Check the error messages above.' echo '' return 71 fi echo "INFO: Anaconda environment '$__env_name' activated." return 0 } activate_nand_riot () { if [ -f "$RIOTBASE/dist/tools/esptools/export.sh" ]; then . "$RIOTBASE/dist/tools/esptools/export.sh" esp32s3 > /dev/null fi if [ -f "$IDF_PATH/export.sh" ]; then . "$IDF_PATH/export.sh" > /dev/null 2>&1 fi echo "INFO: '$NANDBASE' activated. To deactivate: exit and restart the shell." return 0 } activate_nand_esp() { if [ -f "$IDF_PATH/export.sh" ]; then . "$IDF_PATH/export.sh" > /dev/null 2>&1 fi echo "INFO: '$NANDBASE' activated. To deactivate: exit and restart the shell." return 0 } __current_cmd="$(basename $0)" # Step 1: Verify required dependencies check_deps || return $? # Step 2: Validate the provided command case "$__current_cmd" in 'activate-nand-riot' | 'anr' | \ 'activate-nand-esp' | 'ane') ;; *) echo 'ERROR: The command is not supported.' echo '' echo ' expected: activate-nand-riot (= anr)' echo ' activate-nand-esp (= ane)' echo " got: $__current_cmd" echo '' return 121 ;; esac # Step 3: Set the env paths case "$__current_cmd" in 'activate-nand-riot' | 'anr') export NANDBASE='riot' export NANDBASE_PATH="$NANDBASE_ROOT/$NANDBASE" export RIOTBASE="$NANDBASE_PATH/RIOT" export IDF_PATH="$NANDBASE_PATH/esp-idf" export IDF_TOOLS_PATH="$NANDBASE_PATH/.espressif" export CONDA_ENV_NAME="do-nand-$NANDBASE" export DEPS_FLAG="$NANDBASE_PATH/.deps-installed" ;; 'activate-nand-esp' | 'ane') export NANDBASE='esp' export NANDBASE_PATH="$NANDBASE_ROOT/$NANDBASE" export IDF_PATH="$NANDBASE_PATH/esp-idf" export IDF_TOOLS_PATH="$NANDBASE_PATH/.espressif" export CONDA_ENV_NAME="do-nand-$NANDBASE" export DEPS_FLAG="$NANDBASE_PATH/.deps-installed" ;; esac # Step 4: Execute the appropriate command case "$__current_cmd" in 'activate-nand-riot' | 'anr') activate_conda || return $? check_deps_riot || return $? activate_nand_riot || return $? ;; 'activate-nand-esp' | 'ane') check_deps_esp || return $? activate_nand_esp || return $? ;; esac