diff --git a/bin/shpkg b/bin/shpkg
index 037e304..a7d7619 100755
--- a/bin/shpkg
+++ b/bin/shpkg
@@ -5,9 +5,10 @@ set -e
# Config
SHPKG_DIR=${SHPKG_DIR:-~/shpkg}
+SHPKG_SHARE_DIR="${SHPKG_DIR}/share/shpkg"
# SHPKG
-. ${SHPKG_DIR}/lib/shpkg.subr
+. ${SHPKG_SHARE_DIR}/shpkg.subr
# CLI
if [ "x$1" = "xbuild" ]; then
diff --git a/lib/shpkg.subr b/lib/shpkg.subr
deleted file mode 100644
index 866959e..0000000
--- a/lib/shpkg.subr
+++ /dev/null
@@ -1,362 +0,0 @@
-#!/bin/sh
-# Copyright 2023 Thomas de Grivel <thodg@kmx.io>
-
-set -e
-
-# Config
-SHPKG_DIR="${SHPKG_DIR:-${HOME}/shpkg}"
-if [ "x${CC}" = "x" ]; then
- if which cc >/dev/null; then
- CC=cc
- elif which gcc >/dev/null; then
- CC=gcc
- elif which egcc >/dev/null; then
- CC=egcc
- else
- echo "C compiler not found." >&2
- exit 1
- fi
-fi
-SHPKG_PREFIX="${SHPKG_DIR}"
-SHPKG_TARGET="$(${CC} -v 2>&1 | grep '^Target: ' | head -n 1 | cut -c 9-)"
-SHPKG_TARGET_DIR="${SHPKG_DIR}/target/${SHPKG_TARGET}"
-SHPKG_FAKE_DIR="${SHPKG_TARGET_DIR}/fake"
-SHPKG_INCLUDE_DIR="${SHPKG_DIR}/include"
-SHPKG_LIB_DIR="${SHPKG_DIR}/lib"
-SHPKG_OBJ_DIR="${SHPKG_TARGET_DIR}/obj"
-SHPKG_PACKAGE_DIR="${SHPKG_TARGET_DIR}/packages"
-SHPKG_SRC_DIR="${SHPKG_DIR}/src"
-SHPKG_TAG_DIR="${SHPKG_TARGET_DIR}/tag"
-SHPKG_VAR_DB_DIR="${SHPKG_DIR}/var/db/shpkg"
-
-if which sha256 >/dev/null; then
- SHPKG_SHA256=sha256
-elif which sha256sum >/dev/null; then
- SHPKG_SHA256=sha256sum
-else
- echo "sha256 executable not found" >&2
- exit 1
-fi
-
-export CPPFLAGS="${CPPFLAGS} -I${SHPKG_INCLUDE_DIR}"
-export LDFLAGS="${LDFLAGS} -L${SHPKG_LIB_DIR}"
-export PKG_CONFIG_PATH="${SHPKG_LIB_DIR}/pkgconfig"
-
-verbose () {
- echo "$@"
- "$@"
-}
-
-# Setup
-if ! [ -d "${SHPKG_FAKE_DIR}" ]; then
- verbose mkdir -p "${SHPKG_FAKE_DIR}"
-fi
-if ! [ -d "${SHPKG_PACKAGE_DIR}" ]; then
- verbose mkdir -p "${SHPKG_PACKAGE_DIR}"
-fi
-if ! [ -d "${SHPKG_SRC_DIR}" ]; then
- verbose mkdir -p "${SHPKG_SRC_DIR}"
-fi
-if ! [ -d "${SHPKG_VAR_DB_DIR}" ]; then
- verbose mkdir -p "${SHPKG_VAR_DB_DIR}"
-fi
-
-# SHA256
-shpkg_sha256 () {
- sha256 "$@"
-}
-
-shpkg_sha256sum () {
- for F; do
- echo -n "SHA256 ($F) = "
- sha256sum "$F" | cut -d ' ' -f 1
- done
-}
-
-
-# Source repository
-SHPKG_REPO_INDEX="${SHPKG_DIR}/repo_index"
-if ! [ -f "${SHPKG_REPO_INDEX}" ]; then
- echo "${SHPKG_REPO_INDEX}: not found" >&2
- exit 1
-fi
-
-shpkg_clone () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_PARENT_DIR="$(shpkg_src_parent_dir "${REPO}")"
- SHPKG_REPO_GIT_URL="$(shpkg_git_url "${REPO}")"
- SHPKG_REPO_BASENAME="$(basename "${SHPKG_REPO_DIR}")"
- if ! [ -d "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" ]; then
- verbose mkdir -p "${SHPKG_SRC_DIR}/${SHPKG_REPO_PARENT_DIR}"
- ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_PARENT_DIR}" &&
- verbose git clone "${SHPKG_REPO_GIT_URL}" \
- "${SHPKG_REPO_BASENAME}" &&
- verbose cd "${SHPKG_REPO_BASENAME}" &&
- verbose git submodule init &&
- verbose git submodule update
- )
- fi
- done
-}
-
-shpkg_depends_on () {
- shpkg_repo_info "$@" | cut -d ' ' -f 4 | tr ',' ' '
-}
-
-shpkg_fetch () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
- verbose git fetch
- )
- done
-}
-
-shpkg_repo_info () {
- [ "x$#" = "x1" ] || return 1
- grep "^$1 " "${SHPKG_REPO_INDEX}"
-}
-
-shpkg_git_url () {
- shpkg_repo_info "$@" | cut -d ' ' -f 3
-}
-
-shpkg_pull () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
- verbose git pull; )
- done
-}
-
-shpkg_remove () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_PARENT_DIR="$(shpkg_src_parent_dir "${REPO}")"
- verbose rm -rf "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
- rmdir "${SHPKG_SRC_DIR}/${SHPKG_REPO_PARENT_DIR}" 2>/dev/null || true
- done
-}
-
-shpkg_dir () {
- shpkg_repo_info "$@" | cut -d ' ' -f 2
-}
-
-shpkg_src_parent_dir () {
- dirname "$(shpkg_dir "${REPO}")"
-}
-
-shpkg_version () {
- SHPKG_REPO_DIR="$(shpkg_dir "$1")"
- SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
- if [ -d "${SHPKG_REPO_SRC_DIR}/.git" ]; then
- SHPKG_REPO_HASH="$(git -C "${SHPKG_REPO_SRC_DIR}" show-ref --head HEAD | cut -d ' ' -f 1 | head -n 1)"
- SHPKG_REPO_HEAD="$(git -C "${SHPKG_REPO_SRC_DIR}" show-ref | grep "${SHPKG_REPO_HASH}" | grep ' refs/heads/' | sed -e 's,^.* refs/heads/,,')"
- echo "${SHPKG_REPO_HEAD}-${SHPKG_REPO_HASH}"
- fi
-}
-
-# Building from sources
-shpkg_autogen () {
- verbose shpkg_clone "$@"
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
- if [ -x "${SHPKG_REPO_SRC_DIR}/autogen" ]; then
- ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
- verbose ./autogen; )
- elif [ -f "${SHPKG_REPO_SRC_DIR}/autogen.sh" ]; then
- ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
- verbose sh autogen.sh; )
- elif [ -x "${SHPKG_REPO_SRC_DIR}/bootstrap" ]; then
- ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
- verbose ./bootstrap; )
- fi
- done
-}
-
-shpkg_build () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
- if shpkg__tag_is_absent build-done; then
- ( verbose shpkg_configure "${REPO}"; )
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- if [ -f "${SHPKG_REPO_SRC_DIR}/Makefile" ]; then
- ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
- verbose make; )
- elif [ -f "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}/CMakeLists.txt" ]; then
- cmake --build "${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}"
- fi
- shpkg__tag_write build-done
- fi
- done
-}
-
-shpkg_checksum () {
- find . -type f | cut -c 3- | while read F; do
- "shpkg_${SHPKG_SHA256}" "$F"
- done
-}
-
-shpkg_configure () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
- SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- if shpkg__tag_is_absent configure-done; then
- ( verbose shpkg_autogen "${REPO}"; )
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- if ! [ -d "${SHPKG_REPO_FAKE_DIR}" ]; then
- verbose mkdir -p "${SHPKG_REPO_FAKE_DIR}"
- fi
- if [ -x "${SHPKG_REPO_SRC_DIR}/configure" ]; then
- ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
- verbose ./configure --prefix "${SHPKG_PREFIX}"; )
- elif [ -x "${SHPKG_REPO_SRC_DIR}/configure.sh" ]; then
- ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
- verbose ./configure.sh --prefix "${SHPKG_PREFIX}"; )
- elif [ -f "${SHPKG_REPO_SRC_DIR}/CMakeLists.txt" ]; then
- cmake -S "${SHPKG_REPO_SRC_DIR}" -B "${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}" -D CMAKE_INSTALL_PREFIX:PATH="${SHPKG_PREFIX}" -D BUILD_SHARED_LIBS=ON
- fi
- shpkg__tag_write configure-done
- fi
- done
-}
-
-shpkg_fake () {
- verbose shpkg_build "$@"
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
- SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
- if [ -d "${SHPKG_REPO_FAKE_DIR}" ]; then
- verbose rm -rf "${SHPKG_REPO_FAKE_DIR}"
- fi
- verbose mkdir -p "${SHPKG_REPO_FAKE_DIR}"
- if [ -f "${SHPKG_REPO_SRC_DIR}/Makefile" ]; then
- ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
- verbose make prefix="${SHPKG_REPO_FAKE_DIR}" install; )
- elif [ -f "${SHPKG_REPO_SRC_DIR}/CMakeLists.txt" ]; then
- cmake --install "${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}" --prefix "${SHPKG_REPO_FAKE_DIR}"
- fi
- done
-}
-
-shpkg_fake_dir () {
- echo "${SHPKG_FAKE_DIR}/$(shpkg_dir "${REPO}")"
-}
-
-shpkg_package () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
- if ! [ -f "${SHPKG_REPO_PACKAGE}" ]; then
- SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
- verbose shpkg_fake "${REPO}"
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
- SHPKG_REPO_PACKAGE_CHECKSUM="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.SHA256"
- SHPKG_REPO_PACKAGE_DIR="$(dirname "${SHPKG_REPO_PACKAGE}")"
- if ! [ -d "${SHPKG_REPO_PACKAGE_DIR}" ]; then
- verbose mkdir -p "${SHPKG_REPO_PACKAGE_DIR}"
- fi
- ( verbose cd "${SHPKG_REPO_FAKE_DIR}" &&
- echo "shpkg_checksum > ${SHPKG_REPO_PACKAGE_CHECKSUM}" &&
- shpkg_checksum > "${SHPKG_REPO_PACKAGE_CHECKSUM}" &&
- echo "pax -wz . > ${SHPKG_REPO_PACKAGE}" &&
- pax -wz . > "${SHPKG_REPO_PACKAGE}" )
- fi
- done
-}
-
-# requires checked-out sources (git clone first)
-shpkg__tag_is_absent() {
- SHPKG_REPO_TAG_DIR="${SHPKG_TAG_DIR}/${SHPKG_REPO_DIR}/${SHPKG_REPO_VERSION}"
- ! [ -f "${SHPKG_REPO_TAG_DIR}/$1" ]
-}
-
-shpkg__tag_write() {
- SHPKG_REPO_TAG_DIR="${SHPKG_TAG_DIR}/${SHPKG_REPO_DIR}/${SHPKG_REPO_VERSION}"
- DATE="$(date +%F\ %T)"
- if ! [ -d "${SHPKG_REPO_TAG_DIR}" ]; then
- verbose mkdir -p "${SHPKG_REPO_TAG_DIR}"
- fi
- echo "echo ${DATE} > ${SHPKG_REPO_TAG_DIR}/$1"
- echo "${DATE}" > "${SHPKG_REPO_TAG_DIR}/$1"
-}
-
-# Packages
-shpkg_install () {
- for REPO; do
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
- SHPKG_REPO_INSTALLED="${SHPKG_VAR_DB_DIR}/installed/${SHPKG_REPO_DIR}"
- SHPKG_REPO_INSTALLED_DIR="$(dirname "${SHPKG_REPO_INSTALLED}")"
- if ! [ -f "${SHPKG_REPO_INSTALLED}" ] ||
- ! head -n 1 < "${SHPKG_REPO_INSTALLED}" |
- grep "Version: ${SHPKG_REPO_VERSION}" >/dev/null; then
- ( verbose shpkg_install_dependencies "${REPO}"; )
- ( verbose shpkg_build "${REPO}"; )
- ( verbose shpkg_package "${REPO}"; )
- SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
- SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
- SHPKG_REPO_PACKAGE_CHECKSUM="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.SHA256"
- ( verbose cd "${SHPKG_DIR}" &&
- echo "pax -rdz < ${SHPKG_REPO_PACKAGE}" &&
- pax -rdz < "${SHPKG_REPO_PACKAGE}"; )
- if ! [ -d "${SHPKG_REPO_INSTALLED_DIR}" ]; then
- verbose mkdir -p "${SHPKG_REPO_INSTALLED_DIR}"
- fi
- echo "echo Version: ${SHPKG_REPO_VERSION} > ${SHPKG_REPO_INSTALLED}"
- echo "Version: ${SHPKG_REPO_VERSION}" > "${SHPKG_REPO_INSTALLED}"
- echo "cat ${SHPKG_REPO_PACKAGE_CHECKSUM} >> ${SHPKG_REPO_INSTALLED}"
- cat "${SHPKG_REPO_PACKAGE_CHECKSUM}" >> "${SHPKG_REPO_INSTALLED}"
- fi
- done
-}
-
-shpkg_install_dependencies () {
- for REPO; do
- SHPKG_REPO_DEPENDS_ON="$(shpkg_depends_on "${REPO}")"
- if [ "x${SHPKG_REPO_DEPENDS_ON}" != "x" ]; then
- ( verbose shpkg_install ${SHPKG_REPO_DEPENDS_ON}; )
- fi
- done
-}
-
-# TODO: remove package files: hash files on install and delete them if not changed
-# TODO: remove metadata about installed packages
-shpkg_uninstall () {
- for REPO; do
- :
- done
-}
-
-shpkg_upgrade () {
- verbose shpkg_pull "$@"
- verbose shpkg_build "$@"
- verbose shpkg_package "$@"
- verbose shpkg_install "$@"
-}
-
-# Meta
-shpkg_clean() {
- for REPO; do
- ( verbose shpkg_uninstall "${REPO}"; )
- SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
- SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
- rm -rf "${SHPKG_REPO_FAKE_DIR}"
- SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}"
- rm -rf "${SHPKG_REPO_PACKAGE}"-*
- SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
- rm -rf "${SHPKG_REPO_SRC_DIR}"
- SHPKG_REPO_TAG_DIR="${SHPKG_TAG_DIR}/${SHPKG_REPO_DIR}"
- rm -rf "${SHPKG_REPO_TAG_DIR}"
- done
-}
diff --git a/repo_index b/repo_index
deleted file mode 100644
index 85e9cb4..0000000
--- a/repo_index
+++ /dev/null
@@ -1,10 +0,0 @@
-# name directory git-url depends-on
-c3 c3-lang/c3 https://git.kmx.io/c3-lang/c3.git libbsd,libmd
-glfw3 glfw/glfw https://github.com/glfw/glfw.git
-help2man gnu.org/help2man https://git.kmx.io/gnu/help2man.git
-libbsd freedesktop.org/libbsd https://gitlab.freedesktop.org/libbsd/libbsd.git libmd
-libmd hadrons.org/libmd https://git.hadrons.org/git/libmd.git
-libtool gnu.org/libtool git://git.savannah.gnu.org/libtool.git help2man,texinfo
-pkg-config freedesktop.org/pkg-config https://gitlab.freedesktop.org/pkg-config/pkg-config.git
-rtbuf rtbuf/rtbuf https://git.kmx.io/rtbuf/rtbuf.git glfw3
-texinfo gnu.org/texinfo https://git.savannah.gnu.org/git/texinfo.git
\ No newline at end of file
diff --git a/share/config.site b/share/config.site
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/share/config.site
diff --git a/share/shpkg/repo_index b/share/shpkg/repo_index
new file mode 100644
index 0000000..85e9cb4
--- /dev/null
+++ b/share/shpkg/repo_index
@@ -0,0 +1,10 @@
+# name directory git-url depends-on
+c3 c3-lang/c3 https://git.kmx.io/c3-lang/c3.git libbsd,libmd
+glfw3 glfw/glfw https://github.com/glfw/glfw.git
+help2man gnu.org/help2man https://git.kmx.io/gnu/help2man.git
+libbsd freedesktop.org/libbsd https://gitlab.freedesktop.org/libbsd/libbsd.git libmd
+libmd hadrons.org/libmd https://git.hadrons.org/git/libmd.git
+libtool gnu.org/libtool git://git.savannah.gnu.org/libtool.git help2man,texinfo
+pkg-config freedesktop.org/pkg-config https://gitlab.freedesktop.org/pkg-config/pkg-config.git
+rtbuf rtbuf/rtbuf https://git.kmx.io/rtbuf/rtbuf.git glfw3
+texinfo gnu.org/texinfo https://git.savannah.gnu.org/git/texinfo.git
\ No newline at end of file
diff --git a/share/shpkg/shpkg.subr b/share/shpkg/shpkg.subr
new file mode 100644
index 0000000..572c6d8
--- /dev/null
+++ b/share/shpkg/shpkg.subr
@@ -0,0 +1,370 @@
+#!/bin/sh
+# Copyright 2023 Thomas de Grivel <thodg@kmx.io>
+
+set -e
+
+# Config
+SHPKG_DIR="${SHPKG_DIR:-${HOME}/shpkg}"
+
+if [ "x${CC}" = "x" ]; then
+ if which cc >/dev/null; then
+ CC=cc
+ elif which gcc >/dev/null; then
+ CC=gcc
+ elif which egcc >/dev/null; then
+ CC=egcc
+ else
+ echo "C compiler not found." >&2
+ exit 1
+ fi
+fi
+
+SHPKG_PREFIX="${SHPKG_DIR}"
+
+if which sha256 >/dev/null; then
+ SHPKG_SHA256=sha256
+elif which sha256sum >/dev/null; then
+ SHPKG_SHA256=sha256sum
+else
+ echo "sha256 executable not found" >&2
+ exit 1
+fi
+
+SHPKG_TARGET="$(${CC} -v 2>&1 | grep '^Target: ' | head -n 1 | cut -c 9-)"
+
+SHPKG_ETC_DIR="${SHPKG_DIR}/etc/shpkg"
+SHPKG_INCLUDE_DIR="${SHPKG_DIR}/include"
+SHPKG_LIB_DIR="${SHPKG_DIR}/lib"
+SHPKG_SHARE_DIR="${SHPKG_DIR}/share/shpkg"
+SHPKG_SRC_DIR="${SHPKG_DIR}/src"
+SHPKG_TARGET_DIR="${SHPKG_DIR}/target/${SHPKG_TARGET}"
+SHPKG_VAR_DB_DIR="${SHPKG_DIR}/var/db/shpkg"
+
+SHPKG_FAKE_DIR="${SHPKG_TARGET_DIR}/fake"
+SHPKG_OBJ_DIR="${SHPKG_TARGET_DIR}/obj"
+SHPKG_OS_DIR="${SHPKG_SHARE_DIR}/share/shpkg"
+SHPKG_PACKAGE_DIR="${SHPKG_TARGET_DIR}/packages"
+SHPKG_TAG_DIR="${SHPKG_TARGET_DIR}/tag"
+
+export CPPFLAGS="${CPPFLAGS} -I${SHPKG_INCLUDE_DIR}"
+export LDFLAGS="${LDFLAGS} -L${SHPKG_LIB_DIR}"
+export PKG_CONFIG_PATH="${SHPKG_LIB_DIR}/pkgconfig"
+
+verbose () {
+ echo "$@"
+ "$@"
+}
+
+# Setup
+if ! [ -d "${SHPKG_FAKE_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_FAKE_DIR}"
+fi
+if ! [ -d "${SHPKG_PACKAGE_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_PACKAGE_DIR}"
+fi
+if ! [ -d "${SHPKG_SRC_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_SRC_DIR}"
+fi
+if ! [ -d "${SHPKG_VAR_DB_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_VAR_DB_DIR}"
+fi
+
+# SHA256
+shpkg_sha256 () {
+ sha256 "$@"
+}
+
+shpkg_sha256sum () {
+ for F; do
+ echo -n "SHA256 ($F) = "
+ sha256sum "$F" | cut -d ' ' -f 1
+ done
+}
+
+
+# Source repository
+SHPKG_REPO_INDEX="${SHPKG_SHARE_DIR}/repo_index"
+if ! [ -f "${SHPKG_REPO_INDEX}" ]; then
+ echo "${SHPKG_REPO_INDEX}: not found" >&2
+ exit 1
+fi
+
+shpkg_clone () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_PARENT_DIR="$(shpkg_src_parent_dir "${REPO}")"
+ SHPKG_REPO_GIT_URL="$(shpkg_git_url "${REPO}")"
+ SHPKG_REPO_BASENAME="$(basename "${SHPKG_REPO_DIR}")"
+ if ! [ -d "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_SRC_DIR}/${SHPKG_REPO_PARENT_DIR}"
+ ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_PARENT_DIR}" &&
+ verbose git clone "${SHPKG_REPO_GIT_URL}" \
+ "${SHPKG_REPO_BASENAME}" &&
+ verbose cd "${SHPKG_REPO_BASENAME}" &&
+ verbose git submodule init &&
+ verbose git submodule update
+ )
+ fi
+ done
+}
+
+shpkg_depends_on () {
+ shpkg_repo_info "$@" | cut -d ' ' -f 4 | tr ',' ' '
+}
+
+shpkg_fetch () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
+ verbose git fetch
+ )
+ done
+}
+
+shpkg_repo_info () {
+ [ "x$#" = "x1" ] || return 1
+ grep "^$1 " "${SHPKG_REPO_INDEX}"
+}
+
+shpkg_git_url () {
+ shpkg_repo_info "$@" | cut -d ' ' -f 3
+}
+
+shpkg_pull () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
+ verbose git pull; )
+ done
+}
+
+shpkg_remove () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_PARENT_DIR="$(shpkg_src_parent_dir "${REPO}")"
+ verbose rm -rf "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
+ rmdir "${SHPKG_SRC_DIR}/${SHPKG_REPO_PARENT_DIR}" 2>/dev/null || true
+ done
+}
+
+shpkg_dir () {
+ shpkg_repo_info "$@" | cut -d ' ' -f 2
+}
+
+shpkg_src_parent_dir () {
+ dirname "$(shpkg_dir "${REPO}")"
+}
+
+shpkg_version () {
+ SHPKG_REPO_DIR="$(shpkg_dir "$1")"
+ SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
+ if [ -d "${SHPKG_REPO_SRC_DIR}/.git" ]; then
+ SHPKG_REPO_HASH="$(git -C "${SHPKG_REPO_SRC_DIR}" show-ref --head HEAD | cut -d ' ' -f 1 | head -n 1)"
+ SHPKG_REPO_HEAD="$(git -C "${SHPKG_REPO_SRC_DIR}" show-ref | grep "${SHPKG_REPO_HASH}" | grep ' refs/heads/' | sed -e 's,^.* refs/heads/,,')"
+ echo "${SHPKG_REPO_HEAD}-${SHPKG_REPO_HASH}"
+ fi
+}
+
+# Building from sources
+shpkg_autogen () {
+ verbose shpkg_clone "$@"
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
+ if [ -x "${SHPKG_REPO_SRC_DIR}/autogen" ]; then
+ ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
+ verbose ./autogen; )
+ elif [ -f "${SHPKG_REPO_SRC_DIR}/autogen.sh" ]; then
+ ( verbose cd "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}" &&
+ verbose sh autogen.sh; )
+ elif [ -x "${SHPKG_REPO_SRC_DIR}/bootstrap" ]; then
+ ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
+ verbose ./bootstrap; )
+ fi
+ done
+}
+
+shpkg_build () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
+ if shpkg__tag_is_absent build-done; then
+ ( verbose shpkg_configure "${REPO}"; )
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ if [ -f "${SHPKG_REPO_SRC_DIR}/Makefile" ]; then
+ ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
+ verbose make; )
+ elif [ -f "${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}/CMakeLists.txt" ]; then
+ cmake --build "${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}"
+ fi
+ shpkg__tag_write build-done
+ fi
+ done
+}
+
+shpkg_checksum () {
+ find . -type f | cut -c 3- | while read F; do
+ "shpkg_${SHPKG_SHA256}" "$F"
+ done
+}
+
+shpkg_configure () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
+ SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ if shpkg__tag_is_absent configure-done; then
+ ( verbose shpkg_autogen "${REPO}"; )
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ if ! [ -d "${SHPKG_REPO_FAKE_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_REPO_FAKE_DIR}"
+ fi
+ if [ -x "${SHPKG_REPO_SRC_DIR}/configure" ]; then
+ ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
+ verbose ./configure --prefix "${SHPKG_PREFIX}"; )
+ elif [ -x "${SHPKG_REPO_SRC_DIR}/configure.sh" ]; then
+ ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
+ verbose ./configure.sh --prefix "${SHPKG_PREFIX}"; )
+ elif [ -f "${SHPKG_REPO_SRC_DIR}/CMakeLists.txt" ]; then
+ cmake -S "${SHPKG_REPO_SRC_DIR}" -B "${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}" -D CMAKE_INSTALL_PREFIX:PATH="${SHPKG_PREFIX}" -D BUILD_SHARED_LIBS=ON
+ fi
+ shpkg__tag_write configure-done
+ fi
+ done
+}
+
+shpkg_fake () {
+ verbose shpkg_build "$@"
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
+ SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
+ if [ -d "${SHPKG_REPO_FAKE_DIR}" ]; then
+ verbose rm -rf "${SHPKG_REPO_FAKE_DIR}"
+ fi
+ verbose mkdir -p "${SHPKG_REPO_FAKE_DIR}"
+ if [ -f "${SHPKG_REPO_SRC_DIR}/Makefile" ]; then
+ ( verbose cd "${SHPKG_REPO_SRC_DIR}" &&
+ verbose make prefix="${SHPKG_REPO_FAKE_DIR}" install; )
+ elif [ -f "${SHPKG_REPO_SRC_DIR}/CMakeLists.txt" ]; then
+ cmake --install "${SHPKG_OBJ_DIR}/${SHPKG_REPO_DIR}" --prefix "${SHPKG_REPO_FAKE_DIR}"
+ fi
+ done
+}
+
+shpkg_fake_dir () {
+ echo "${SHPKG_FAKE_DIR}/$(shpkg_dir "${REPO}")"
+}
+
+shpkg_package () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
+ if ! [ -f "${SHPKG_REPO_PACKAGE}" ]; then
+ SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
+ verbose shpkg_fake "${REPO}"
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
+ SHPKG_REPO_PACKAGE_CHECKSUM="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.SHA256"
+ SHPKG_REPO_PACKAGE_DIR="$(dirname "${SHPKG_REPO_PACKAGE}")"
+ if ! [ -d "${SHPKG_REPO_PACKAGE_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_REPO_PACKAGE_DIR}"
+ fi
+ ( verbose cd "${SHPKG_REPO_FAKE_DIR}" &&
+ echo "shpkg_checksum > ${SHPKG_REPO_PACKAGE_CHECKSUM}" &&
+ shpkg_checksum > "${SHPKG_REPO_PACKAGE_CHECKSUM}" &&
+ echo "pax -wz . > ${SHPKG_REPO_PACKAGE}" &&
+ pax -wz . > "${SHPKG_REPO_PACKAGE}" )
+ fi
+ done
+}
+
+# requires checked-out sources (git clone first)
+shpkg__tag_is_absent() {
+ SHPKG_REPO_TAG_DIR="${SHPKG_TAG_DIR}/${SHPKG_REPO_DIR}/${SHPKG_REPO_VERSION}"
+ ! [ -f "${SHPKG_REPO_TAG_DIR}/$1" ]
+}
+
+shpkg__tag_write() {
+ SHPKG_REPO_TAG_DIR="${SHPKG_TAG_DIR}/${SHPKG_REPO_DIR}/${SHPKG_REPO_VERSION}"
+ DATE="$(date +%F\ %T)"
+ if ! [ -d "${SHPKG_REPO_TAG_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_REPO_TAG_DIR}"
+ fi
+ echo "echo ${DATE} > ${SHPKG_REPO_TAG_DIR}/$1"
+ echo "${DATE}" > "${SHPKG_REPO_TAG_DIR}/$1"
+}
+
+# Packages
+shpkg_install () {
+ for REPO; do
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
+ SHPKG_REPO_INSTALLED="${SHPKG_VAR_DB_DIR}/installed/${SHPKG_REPO_DIR}"
+ SHPKG_REPO_INSTALLED_DIR="$(dirname "${SHPKG_REPO_INSTALLED}")"
+ if ! [ -f "${SHPKG_REPO_INSTALLED}" ] ||
+ ! head -n 1 < "${SHPKG_REPO_INSTALLED}" |
+ grep "Version: ${SHPKG_REPO_VERSION}" >/dev/null; then
+ ( verbose shpkg_install_dependencies "${REPO}"; )
+ ( verbose shpkg_build "${REPO}"; )
+ ( verbose shpkg_package "${REPO}"; )
+ SHPKG_REPO_VERSION="$(shpkg_version "${REPO}")"
+ SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.tgz"
+ SHPKG_REPO_PACKAGE_CHECKSUM="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}-${SHPKG_REPO_VERSION}.SHA256"
+ ( verbose cd "${SHPKG_DIR}" &&
+ echo "pax -rdz < ${SHPKG_REPO_PACKAGE}" &&
+ pax -rdz < "${SHPKG_REPO_PACKAGE}"; )
+ if ! [ -d "${SHPKG_REPO_INSTALLED_DIR}" ]; then
+ verbose mkdir -p "${SHPKG_REPO_INSTALLED_DIR}"
+ fi
+ echo "echo Version: ${SHPKG_REPO_VERSION} > ${SHPKG_REPO_INSTALLED}"
+ echo "Version: ${SHPKG_REPO_VERSION}" > "${SHPKG_REPO_INSTALLED}"
+ echo "cat ${SHPKG_REPO_PACKAGE_CHECKSUM} >> ${SHPKG_REPO_INSTALLED}"
+ cat "${SHPKG_REPO_PACKAGE_CHECKSUM}" >> "${SHPKG_REPO_INSTALLED}"
+ fi
+ done
+}
+
+shpkg_install_dependencies () {
+ for REPO; do
+ SHPKG_REPO_DEPENDS_ON="$(shpkg_depends_on "${REPO}")"
+ if [ "x${SHPKG_REPO_DEPENDS_ON}" != "x" ]; then
+ ( verbose shpkg_install ${SHPKG_REPO_DEPENDS_ON}; )
+ fi
+ done
+}
+
+# TODO: remove package files: hash files on install and delete them if not changed
+# TODO: remove metadata about installed packages
+shpkg_uninstall () {
+ for REPO; do
+ :
+ done
+}
+
+shpkg_upgrade () {
+ verbose shpkg_pull "$@"
+ verbose shpkg_build "$@"
+ verbose shpkg_package "$@"
+ verbose shpkg_install "$@"
+}
+
+# Meta
+shpkg_clean() {
+ for REPO; do
+ ( verbose shpkg_uninstall "${REPO}"; )
+ SHPKG_REPO_DIR="$(shpkg_dir "${REPO}")"
+ SHPKG_REPO_FAKE_DIR="$(shpkg_fake_dir "${REPO}")"
+ rm -rf "${SHPKG_REPO_FAKE_DIR}"
+ SHPKG_REPO_PACKAGE="${SHPKG_PACKAGE_DIR}/${SHPKG_REPO_DIR}"
+ rm -rf "${SHPKG_REPO_PACKAGE}"-*
+ SHPKG_REPO_SRC_DIR="${SHPKG_SRC_DIR}/${SHPKG_REPO_DIR}"
+ rm -rf "${SHPKG_REPO_SRC_DIR}"
+ SHPKG_REPO_TAG_DIR="${SHPKG_TAG_DIR}/${SHPKG_REPO_DIR}"
+ rm -rf "${SHPKG_REPO_TAG_DIR}"
+ done
+}