dep

Package manager for embedded C libraries
git clone git://git.finwo.net/app/dep
Log | Files | Refs | README | LICENSE

commit 43f088e90a1255fb7159b23c2e11981c1d67a8c0
parent 7180f9df812cc27812e13ae104b32ef070a03fbb
Author: finwo <finwo@pm.me>
Date:   Sat, 28 Jan 2023 03:10:48 +0100

Implemented minimalist add without preloaded repository

Diffstat:
MMakefile | 17++++-------------
Mpackage.ini | 2+-
Asrc/command/add/help.txt | 13+++++++++++++
Asrc/command/add/index.sh | 36++++++++++++++++++++++++++++++++++++
Msrc/command/help/index.sh | 6++++--
Msrc/command/help/topic/global.txt | 4+++-
Dsrc/command/install.sh | 139-------------------------------------------------------------------------------
Asrc/command/install/help.txt | 7+++++++
Asrc/command/install/index.sh | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.sh | 3++-
Msrc/util/ini.sh | 15+++++++++++++++
11 files changed, 228 insertions(+), 157 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,20 +1,12 @@ -SRC=$(wildcard src/*.sh) - -# Idea: -# include lib/.dep/libraries.mk +SRC:= +SRC+=$(wildcard src/*.sh) +SRC+=$(wildcard src/*/*.sh) +SRC+=$(wildcard src/*/*/*.sh) PREPROCESS=preprocess --substitute DESTDIR?=/usr/local TARGET=dep -default: $(TARGET) - -# util/ini.sh: src/util/ini.sh src/util/shopt.sh -# mkdir -p util -# echo '#!/usr/bin/env bash' > $@ -# $(PREPROCESS) -I src -v src/util/ini.sh | tee -a $@ > /dev/null -# chmod +x $@ - $(TARGET): $(SRC) echo '#!/usr/bin/env bash' > "$(TARGET)" $(PREPROCESS) -D __NAME=$(TARGET) -I src src/main.sh | tee -a $(TARGET) > /dev/null @@ -27,4 +19,3 @@ install: $(TARGET) .PHONY: clean clean: rm -f $(TARGET) - # rm -rf util/ini.sh diff --git a/package.ini b/package.ini @@ -1,3 +1,3 @@ [package] -name=dep deps=lib +name=dep diff --git a/src/command/add/help.txt b/src/command/add/help.txt @@ -0,0 +1,13 @@ +Usage: ${NAME} [global options] add <name> <url> + +Description: + + The add command will add a dependency to your package.ini and trigger the + install command to do the actual install. + +Arguments: + + name The name of the dependency that will be installed. This will be used as + the target directory within lib as well. + + url The url pointing to the package.ini that describes the dependency. diff --git a/src/command/add/index.sh b/src/command/add/index.sh @@ -0,0 +1,36 @@ +#include "util/ini.sh" + +read -r -d '' help_topics[add] <<- EOF +# #include "help.txt" +EOF + +CMD_ADD_PKG= +CMD_ADD_SRC= + +function arg_a { + arg_add "$@" + return $? +} +function arg_add { + if [ $# != 2 ]; then + echo "Add command requires 2 arguments" >&2 + exit 1 + fi + + CMD_ADD_PKG="$1" + CMD_ADD_SRC="$2" + + return 0 +} + +function cmd_a { + cmd_add "$@" + return $? +} +function cmd_add { + OLD_PKG=$(ini_foreach ini_output_full "package.ini") + (echo "dependencies.${CMD_ADD_PKG}=${CMD_ADD_SRC}" ; echo -e "${OLD_PKG}") | ini_write "package.ini" +} + +cmds[${#cmds[*]}]="a" +cmds[${#cmds[*]}]="add" diff --git a/src/command/help/index.sh b/src/command/help/index.sh @@ -10,7 +10,9 @@ function arg_h { return $? } function arg_help { - HELP_TOPIC=$1 + if [[ $# -gt 0 ]]; then + HELP_TOPIC=$1 + fi shift } @@ -24,7 +26,7 @@ function cmd_help { exit 1 fi - echo "${help_topics[$HELP_TOPIC]}" + echo -e "\n${help_topics[$HELP_TOPIC]}\n" } cmds[${#cmds[*]}]="h" diff --git a/src/command/help/topic/global.txt b/src/command/help/topic/global.txt @@ -1,12 +1,14 @@ - Usage: ${NAME} [global options] <command> [options] [-- ...args] Global options: n/a Commands: + a(dd) Add a new dependency to the project i(nstall) Install all the project's dependencies h(elp) [topic] Show this help or the top-level info about a command Help topics: global This help text + add More detailed explanation on the add command + install More detailed explanation on the install command diff --git a/src/command/install.sh b/src/command/install.sh @@ -1,139 +0,0 @@ -# #include "util/ini.sh" - -function arg_i { - arg_install "$@" - return $? -} -function arg_install { - return 0 -} - -function cmd_i { - cmd_install "$@" - return $? -} -function cmd_install { - - # Sanity check - PACKAGE_PATH="$(pwd)/package.ini" - if [ ! -f "${PACKAGE_PATH}" ]; then - echo "No package.ini in the working directory!" >&2 - exit 1 - fi - - ini_foreach cmd_install_parse_ini_main "${PACKAGE_PATH}" - cmd_install_execute -} - -cmds[${#cmds[*]}]="i" -cmds[${#cmds[*]}]="install" - -CMD_INSTALL_PKG_NAME= -CMD_INSTALL_PKG_DEST="$(pwd)/lib" -declare -A CMD_INSTALL_DEPS -function cmd_install_parse_ini_main { - case "$1" in - package.) - case "$2" in - name) - CMD_INSTALL_PKG_NAME="$3" - ;; - deps) - CMD_INSTALL_PKG_DEST="$(pwd)/$3" - ;; - esac - ;; - dependencies.) - CMD_INSTALL_DEPS["$2"]="$3" - ;; - esac -} - -function cmd_install_execute { - cmd_install_reset_generated - for key in "${!CMD_INSTALL_DEPS[@]}"; do - cmd_install_dep "$key" "${CMD_INSTALL_DEPS[$key]}" - done -} - -function cmd_install_reset_generated { - rm -rf "${CMD_INSTALL_PKG_DEST}/.__NAME" - mkdir -p "${CMD_INSTALL_PKG_DEST}/.__NAME/include" - echo "INCLUDES+=-I ${CMD_INSTALL_PKG_DEST}/.__NAME/include" > "${CMD_INSTALL_PKG_DEST}/.__NAME/config.mk" -} - -function cmd_install_dep { - name=$1 - origin=$2 - - # Full install if missing - if [ ! -d "${CMD_INSTALL_PKG_DEST}/${name}" ]; then - - # Fetch package.ini for the dependency - mkdir -p "${CMD_INSTALL_PKG_DEST}/${name}" - curl --location --progress-bar "${origin}" --output "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" - - # Fetch it's src (if present) - if [ ! -z "$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.src)" ]; then - SRC="$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.src)" - HASH="$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.src-sha256)" - - # Download - mkdir -p "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}" - if [ ! -f "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" ]; then - curl --location --progress-bar "${SRC}" --output "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" - fi - - # Verify checksum - if [ "${HASH}" != "$(sha256sum "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" | awk '{print $1}')" ]; then - echo "The tarball for '${name}' failed it's checksum!" >&2 - exit 1 - fi - - # Extract tarball - tar --extract --directory "${CMD_INSTALL_PKG_DEST}/${name}/" --strip-components 1 --file="${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" - fi - - # Handle fetching extra files - while read line; do - filename=${line%%=*} - filesource=${line#*=} - - # Download the extra file into cache - mkdir -p "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/fetch" - if [ ! -f "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/fetch/${filename}" ]; then - curl --location --progress-bar "${filesource}" --create-dirs --output "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/fetch/${filename}" - fi - - done < <(ini_foreach ini_output_section "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" "fetch.") - - # Copy the extra files into the target directory - tar --create --directory "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}" "fetch" | \ - tar --extract --directory "${CMD_INSTALL_PKG_DEST}/${name}" --strip-components 1 - fi - - # Download package's dependencies - while read line; do - depname=${line%%=*} - deplink=${line#*=} - cmd_install_dep "$depname" "$deplink" - done < <(ini_foreach ini_output_section "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" "dependencies.") - - # TODO: handle patching/building here - - # Fetch directory key for export absolute paths - DIRKEY="$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.dirkey)" - if [ -z "${DIRKEY}" ]; then - DIRKEY=__DIRNAME__ - fi - - # Build the package's exports - while read line; do - filetarget=${line%%=*} - filesource=${line#*=} - mkdir -p "$(dirname "${CMD_INSTALL_PKG_DEST}/.__NAME/${filetarget}")" - cat "${CMD_INSTALL_PKG_DEST}/${name}/${filesource}" | \ - sed "s|${DIRKEY}|${CMD_INSTALL_PKG_DEST}/${name}|g" \ - >> "${CMD_INSTALL_PKG_DEST}/.__NAME/${filetarget}" - done < <(ini_foreach ini_output_section "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" "export.") -} diff --git a/src/command/install/help.txt b/src/command/install/help.txt @@ -0,0 +1,7 @@ +Usage: ${NAME} [global options] install + +Description: + + The install command will iterate over all dependencies listed in your + project's package.ini and install them 1-by-1, installing the dependency's + dependencies as well. diff --git a/src/command/install/index.sh b/src/command/install/index.sh @@ -0,0 +1,143 @@ +# #include "util/ini.sh" + +read -r -d '' help_topics[install] <<- EOF +# #include "help.txt" +EOF + +function arg_i { + arg_install "$@" + return $? +} +function arg_install { + return 0 +} + +function cmd_i { + cmd_install "$@" + return $? +} +function cmd_install { + + # Sanity check + PACKAGE_PATH="$(pwd)/package.ini" + if [ ! -f "${PACKAGE_PATH}" ]; then + echo "No package.ini in the working directory!" >&2 + exit 1 + fi + + ini_foreach cmd_install_parse_ini_main "${PACKAGE_PATH}" + cmd_install_execute +} + +cmds[${#cmds[*]}]="i" +cmds[${#cmds[*]}]="install" + +CMD_INSTALL_PKG_NAME= +CMD_INSTALL_PKG_DEST="$(pwd)/lib" +declare -A CMD_INSTALL_DEPS +function cmd_install_parse_ini_main { + case "$1" in + package.) + case "$2" in + name) + CMD_INSTALL_PKG_NAME="$3" + ;; + deps) + CMD_INSTALL_PKG_DEST="$(pwd)/$3" + ;; + esac + ;; + dependencies.) + CMD_INSTALL_DEPS["$2"]="$3" + ;; + esac +} + +function cmd_install_execute { + cmd_install_reset_generated + for key in "${!CMD_INSTALL_DEPS[@]}"; do + cmd_install_dep "$key" "${CMD_INSTALL_DEPS[$key]}" + done +} + +function cmd_install_reset_generated { + rm -rf "${CMD_INSTALL_PKG_DEST}/.__NAME" + mkdir -p "${CMD_INSTALL_PKG_DEST}/.__NAME/include" + echo "INCLUDES+=-I ${CMD_INSTALL_PKG_DEST}/.__NAME/include" > "${CMD_INSTALL_PKG_DEST}/.__NAME/config.mk" +} + +function cmd_install_dep { + name=$1 + origin=$2 + + # Full install if missing + if [ ! -d "${CMD_INSTALL_PKG_DEST}/${name}" ]; then + + # Fetch package.ini for the dependency + mkdir -p "${CMD_INSTALL_PKG_DEST}/${name}" + curl --location --progress-bar "${origin}" --output "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" + + # Fetch it's src (if present) + if [ ! -z "$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.src)" ]; then + SRC="$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.src)" + HASH="$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.src-sha256)" + + # Download + mkdir -p "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}" + if [ ! -f "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" ]; then + curl --location --progress-bar "${SRC}" --output "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" + fi + + # Verify checksum + if [ "${HASH}" != "$(sha256sum "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" | awk '{print $1}')" ]; then + echo "The tarball for '${name}' failed it's checksum!" >&2 + exit 1 + fi + + # Extract tarball + tar --extract --directory "${CMD_INSTALL_PKG_DEST}/${name}/" --strip-components 1 --file="${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/tarball" + fi + + # Handle fetching extra files + mkdir -p "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/fetch" + while read line; do + filename=${line%%=*} + filesource=${line#*=} + + # Download the extra file into cache + if [ ! -f "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/fetch/${filename}" ]; then + curl --location --progress-bar "${filesource}" --create-dirs --output "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}/fetch/${filename}" + fi + + done < <(ini_foreach ini_output_section "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" "fetch.") + + # Copy the extra files into the target directory + tar --create --directory "${CMD_INSTALL_PKG_DEST}/.__NAME/cache/${name}" "fetch" | \ + tar --extract --directory "${CMD_INSTALL_PKG_DEST}/${name}" --strip-components 1 + fi + + # Download package's dependencies + while read line; do + depname=${line%%=*} + deplink=${line#*=} + cmd_install_dep "$depname" "$deplink" + done < <(ini_foreach ini_output_section "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" "dependencies.") + + # TODO: handle patching/building here + + # Fetch directory key for export absolute paths + DIRKEY="$(ini_foreach ini_output_value "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" package.dirkey)" + if [ -z "${DIRKEY}" ]; then + DIRKEY=__DIRNAME__ + fi + + # Build the package's exports + while read line; do + filetarget=${line%%=*} + filesource=${line#*=} + mkdir -p "$(dirname "${CMD_INSTALL_PKG_DEST}/.__NAME/${filetarget}")" + cat "${CMD_INSTALL_PKG_DEST}/${name}/${filesource}" | \ + sed "s|${DIRKEY}|${CMD_INSTALL_PKG_DEST}/${name}|g" \ + >> "${CMD_INSTALL_PKG_DEST}/.__NAME/${filetarget}" + done < <(ini_foreach ini_output_section "${CMD_INSTALL_PKG_DEST}/${name}/package.ini" "export.") +} diff --git a/src/main.sh b/src/main.sh @@ -1,6 +1,7 @@ cmds=("") # #include "command/help/index.sh" -# #include "command/install.sh" +# #include "command/add/index.sh" +# #include "command/install/index.sh" function main { cmd=help diff --git a/src/util/ini.sh b/src/util/ini.sh @@ -49,7 +49,22 @@ function ini_foreach { fi done < "${inifile}" +} +function ini_write { + PREVIOUSSECTION= + echo -en "" > "$1" + while read line; do + KEYFULL=${line%%=*} + VALUE=${line#*=} + SECTION=${KEYFULL%%.*} + KEY=${KEYFULL#*.} + if [[ "${SECTION}" != "${PREVIOUSSECTION}" ]]; then + echo "[${SECTION}]" >> "$1" + PREVIOUSSECTION="${SECTION}" + fi + echo "${KEY}=${VALUE}" >> "$1" + done < <(sort --unique) } function ini_output_full {