From 243e102b105037b82deef752aeb3f07899d1db75 Mon Sep 17 00:00:00 2001 From: Strix Date: Thu, 6 Jun 2024 02:01:36 +0200 Subject: [PATCH] init --- .gitignore | 1 + README.md | 8 ++++ bin/a3 | 96 +++++++++++++++++++++++++++++++++++++++++++++ dev | 13 ++++++ doc/declarations.md | 6 +++ lib/a3.sh | 82 ++++++++++++++++++++++++++++++++++++++ lib/include.sh | 21 ++++++++++ lib/log.sh | 37 +++++++++++++++++ lib/util.sh | 9 +++++ meta.a3 | 9 +++++ 10 files changed, 282 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 bin/a3 create mode 100755 dev create mode 100644 doc/declarations.md create mode 100644 lib/a3.sh create mode 100644 lib/include.sh create mode 100644 lib/log.sh create mode 100644 lib/util.sh create mode 100755 meta.a3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b59f7e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +test/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..90abbc6 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# AAA (a3) + +AAA stands for "AAA, I want a package" + +## What does it do? +Manage packages and setup software. + +(It also provides a useful library!) \ No newline at end of file diff --git a/bin/a3 b/bin/a3 new file mode 100755 index 0000000..32ecc48 --- /dev/null +++ b/bin/a3 @@ -0,0 +1,96 @@ +#!/bin/sh + +set -e + +. ${A3_LIB_PATH:-/usr/lib/a3}/include.sh +a3include_lib a3 +a3include_lib log +a3include_lib util + +A3_FILE=$1 +[ -z "$A3_FILE" ] && exit 1 +if ! [ -f "$A3_FILE" ]; then + LOGD "lfa3" + A3_FILE=$(a3index_find $A3_FILE) + [ -z "$A3_FILE" ] && fatal_log "no a3 file found" +fi +shift + +name=$(a3ff a3read_meta name) +description=$(a3ff a3read_meta description) +author=$(a3ff a3read_meta author) +url=$(a3ff a3read_meta url) +require_value meta:a3.name $name + +echo "name: $name" +[ -n "$description" ] && echo "description: $description" +[ -n "$author" ] && echo "author: $author" +[ -n "$url" ] && echo "url: $url" +echo "status: $(a3index_current_status $name || echo "not installed")" +echo "---" + +A3_INSTALL_BIN_PATH=${A3_INSTALL_BIN_PATH:-/usr/bin} +A3_INSTALL_LIB_PATH=${A3_INSTALL_LIB_PATH:-/usr/lib} + +main() { + case $1 in + update) + a3index_is $name installed || fatal_log not installed. + a3index_update $name pending + A3_FILE=$(a3index_find $name) + main install + ;; + install) + a3index_is $name installed && fatal_log "$name is already installed." + oldpwd=$(pwd) + if [ -n "$(a3ff a3read_declaration declare_workdir | head -n 1)" ]; then + cd $(a3ff a3read_declaration declare_workdir | head -n 1) + fi + a3ff a3index_create $name + a3ff a3read_declaration declare_executable | while read ex; do + [ -z "$ex" ] && continue + filename=$(basename $ex) + if [ -f "$A3_INSTALL_BIN_PATH/$filename" ]; then + LOGW "overwriting $A3_INSTALL_BIN_PATH/$filename..." + else + LOGI "copying $ex to $A3_INSTALL_BIN_PATH/$filename..." + fi + cp $ex $A3_INSTALL_BIN_PATH/$filename + chmod +x $A3_INSTALL_BIN_PATH/$filename + done + a3ff a3read_declaration declare_library | while read lib; do + [ -z "$lib" ] && continue + if [ -d "$A3_INSTALL_LIB_PATH/$name" ]; then + LOGW "overwriting $A3_INSTALL_LIB_PATH/$name..." + else + LOGI "copying library..." + fi + cp -r $lib/. $A3_INSTALL_LIB_PATH/$name + done + a3index_update $name installed + cd $oldpwd + ;; + eval) shift; $@ ;; + remove) + a3index_is $name installed || fatal_log "$name is not installed." + a3ff a3read_declaration declare_executable | while read ex; do + filename=$(basename $ex) + [ -f "$A3_INSTALL_BIN_PATH/$filename" ] || fatal_log "$A3_INSTALL_BIN_PATH/$filename does not exist" + LOGI "removing $A3_INSTALL_BIN_PATH/$filename..." + rm $A3_INSTALL_BIN_PATH/$filename + done + a3ff a3read_declaration declare_library | while read lib; do + [ -d "$A3_INSTALL_LIB_PATH/$name" ] || continue + LOGI "removing library..." + rm -r $A3_INSTALL_LIB_PATH/$name + done + a3index_update $name cache + ;; + list) + for f in $(find $A3_INDEX_ROOT -iname "*.a3"); do + echo "$(a3read_meta "$f" name): $(basename $(dirname $f))" + done + esac +} + +main $@ diff --git a/dev b/dev new file mode 100755 index 0000000..ae36feb --- /dev/null +++ b/dev @@ -0,0 +1,13 @@ +#!/bin/sh + +export A3_LIB_PATH="./lib" +export A3_INDEX_ROOT="./test/index" +export A3_INSTALL_BIN_PATH="./test/bin" +export A3_INSTALL_LIB_PATH="./test/lib" + +mkdir -p \ + $A3_INDEX_ROOT \ + $A3_INSTALL_BIN_PATH \ + $A3_INSTALL_LIB_PATH + +exec ./bin/a3 $@ \ No newline at end of file diff --git a/doc/declarations.md b/doc/declarations.md new file mode 100644 index 0000000..8d4f302 --- /dev/null +++ b/doc/declarations.md @@ -0,0 +1,6 @@ +# Declarations for a3 + +| usage | description | +| ----------------------------------- | ------------------------------------------------- | +| `declare_executable ` | the executable to put in /usr/bin | +| `declare_library [lib_name]` | library to put at /usr/lib/(/) | \ No newline at end of file diff --git a/lib/a3.sh b/lib/a3.sh new file mode 100644 index 0000000..fac2008 --- /dev/null +++ b/lib/a3.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +# General purpose for a3 + +# a3ff [args]: runs functions and automatically makes the first arg the file +# a3ff => a3 file function +A3_FILE=${A3_FILE:-} +a3ff() { + [ -z "$A3_FILE" ] && return 1 + local func=$1 + [ -z "$func" ] && return 1 + shift + $func $A3_FILE $@ +} + +A3_INDEX_ROOT=${A3_INDEX_ROOT:-/var/lib/a3/index} + +a3index_create() { + file=$1 + name=$2 + [ -z "$file" ] && return 1 + [ -z "$name" ] && return 1 + [ "$file" = "$A3_INDEX_ROOT/pending/$name.a3" ] && return 0 + mkdir -p $A3_INDEX_ROOT/pending + cp $file $A3_INDEX_ROOT/pending/$name.a3 + if ! grep -q "declare_workdir" $A3_INDEX_ROOT/pending/$name.a3; then + echo -e "\ndeclare_workdir $(pwd)" >> $A3_INDEX_ROOT/pending/$name.a3 + fi +} + +a3index_find() { + name=$1 + [ -z "$name" ] && return 1 + find $A3_INDEX_ROOT -iname "$name.a3" | head -n 1 +} + +a3index_current_status() { + name=$1 + [ -z "$name" ] && return 1 + file=$(a3index_find $name) + [ -z "$file" ] && return 1 + basename $(dirname $file) +} + +a3index_update() { + name=$1 + status=$2 + [ -z "$name" ] && return 1 + [ -z "$status" ] && return 1 + [ -f "$A3_INDEX_ROOT/$status/$name.a3" ] && return 0 + file=$(a3index_find $name) + [ -z "$file" ] && return 1 + mkdir -p $A3_INDEX_ROOT/$status + mv $file $A3_INDEX_ROOT/$status/$name.a3 +} + +a3index_is() { + name=$1 + status=$2 + [ -z "$name" ] && return 1 + [ -z "$status" ] && return 1 + [ -f "$A3_INDEX_ROOT/$status/$name.a3" ] +} + +a3read_declaration() { + file=$1 + declaration=$2 + [ -z "$file" ] && return 1 + [ -z "$declaration" ] && return 1 + shift; shift + grep "$declaration" $file | sed "s/$declaration//" | awk '{$1=$1};1' +} + +a3read_meta() { + file=$1 + prop=$2 + [ -z "$file" ] && return 1 + [ -z "$prop" ] && return 1 + shift; shift + + grep "#a3.$prop:" $file | sed "s/#a3.$prop://" | xargs +} \ No newline at end of file diff --git a/lib/include.sh b/lib/include.sh new file mode 100644 index 0000000..8de9ac1 --- /dev/null +++ b/lib/include.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +if ! [ $A3_INCLUDE ]; then + A3_INCLUDE=1 + A3_INCLUDED="" + A3_LIB_PATH=${A3_LIB_PATH:-/usr/lib/a3} + is_included() { + echo "$A3_INCLUDED" | grep -q "$1" + } + + include() { + [ -z "$1" ] && return 0 + is_included $1 && return 0 + . $1 + A3_INCLUDED="$A3_INCLUDED $1" + } + + a3include_lib() { + include $A3_LIB_PATH/$1.sh + } +fi \ No newline at end of file diff --git a/lib/log.sh b/lib/log.sh new file mode 100644 index 0000000..832d793 --- /dev/null +++ b/lib/log.sh @@ -0,0 +1,37 @@ +#!/bin/sh + + +# levels: +# DEBUG = 0 +# INFO = 1 +# WARN = 2 +# ERROR = 3 +A3_LOG_LEVEL=${A3_LOG_LEVEL:-1} + +__a3_log_level_to_text() { + case $1 in + 0) echo "debug" ;; + 1) echo "info" ;; + 2) echo "warn" ;; + 3) echo "error" ;; + 4) echo "fatal" ;; + esac +} + +__a3_log() { + level=$1 + shift + if [ $level -ge $A3_LOG_LEVEL ]; then + echo "[$(__a3_log_level_to_text $level)] $@" + fi +} + +alias LOGD="__a3_log 0" +alias LOGI="__a3_log 1" +alias LOGW="__a3_log 2" +alias LOGE="__a3_log 3" + +fatal_log() { + __a3_log 4 $@ + exit 1 +} diff --git a/lib/util.sh b/lib/util.sh new file mode 100644 index 0000000..bb12c2d --- /dev/null +++ b/lib/util.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +require_value() { + local name=$1; shift + if [ -z "$@" ]; then + echo "expected value for: $name" + exit 1 + fi +} \ No newline at end of file diff --git a/meta.a3 b/meta.a3 new file mode 100755 index 0000000..768dd27 --- /dev/null +++ b/meta.a3 @@ -0,0 +1,9 @@ +#!bin/a3 + +#a3.name: a3 +#a3.description: a tool to manage packages and setup software. +#a3.author: Strix +#a3.url: https://git.saluco.nl/strix/aaa + +declare_executable ./bin/a3 +declare_library ./lib \ No newline at end of file