diff --git a/Makefile b/Makefile
index dd42319..e0cf900 100644
--- a/Makefile
+++ b/Makefile
@@ -1,15 +1,14 @@
+SUBDIRS := $(wildcard */.)
prefix = /usr
install:
- install -v -m755 matter-mirror/main.py $(DESTDIR)$(prefix)/bin/matter-mirror
- install -v -m755 matter-chroot/main.sh $(DESTDIR)$(prefix)/bin/matter-chroot
- install -v -m755 matter-base/main.sh $(DESTDIR)$(prefix)/bin/matter-base
- install -v -m755 matter-iso/main.sh $(DESTDIR)$(prefix)/bin/matter-iso
+ @for dir in $(SUBDIRS) ; do \
+ $(MAKE) -C "$$dir" install ; \
+ done
uninstall:
- rm -v $(DESTDIR)$(prefix)/bin/matter-mirror
- rm -v $(DESTDIR)$(prefix)/bin/matter-chroot
- rm -v $(DESTDIR)$(prefix)/bin/matter-base
- rm -v $(DESTDIR)$(prefix)/bin/matter-iso
+ @for dir in $(SUBDIRS) ; do \
+ $(MAKE) -C "$$dir" uninstall ; \
+ done
.PHONY: install uninstall
diff --git a/README.md b/README.md
index 480f92e..ab7fe90 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
-# tools | Matterlinux Tools and Scripts Collection
-This repository contains different tools and scripts
-for general matterlinux installation and configuration.
+# mtsc | MatterLinux tools and scripts collection
+This repository contains different tools and scripts
+for general MatterLinux installation, configuration and
+build process.
### Installation
All the tools and scripts can be copied to PATH with
@@ -8,10 +9,14 @@ the make script:
```
make install
```
+You can also install the mtsc package from the base package
+pool.
### Usage
All tools/scripts contains usage information in README files:
+- [mtsc-common](mtsc-common/README.md)
- [matter-chroot](matter-chroot/README.md)
-- [matter-mirror](matter-mirror/README.md)
- [matter-base](matter-base/README.md)
- [matter-iso](matter-iso/README.md)
+- [mp-build](mp-build/README.md)
+- [mp-pool](mp-pool/README.md)
diff --git a/matter-base/Makefile b/matter-base/Makefile
new file mode 100644
index 0000000..197bf65
--- /dev/null
+++ b/matter-base/Makefile
@@ -0,0 +1,9 @@
+PREFIX = /usr
+
+install:
+ install -m755 "main.sh" $(DESTDIR)/$(PREFIX)/bin/matter-base
+
+uninstall:
+ rm $(DESTDIR)/$(PREFIX)/lib/matter-base
+
+.PHONY: install uninstall
diff --git a/matter-base/README.md b/matter-base/README.md
index c19c265..b9c88cb 100644
--- a/matter-base/README.md
+++ b/matter-base/README.md
@@ -3,7 +3,7 @@ This script is used for building release archives.
### Usage
Note that you will need to install and configure
-[`mp`](https://git.matterlinux.xyz/matterlinux/mp) before using
+[`matt`](https://git.matterlinux.xyz/matterlinux/matt) before using
`matter-base`.
To use the `matter-base` script, specify a temporary target
diff --git a/matter-base/main.sh b/matter-base/main.sh
old mode 100644
new mode 100755
index 4eae73f..b1b7240
--- a/matter-base/main.sh
+++ b/matter-base/main.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# matter-base | Matterlinux Release Archive Build Script
+# matter-base | MatterLinux release archive build script
# MatterLinux 2023-2024 (https://matterlinux.xyz)
# This program is free software: you can redistribute it and/or modify
@@ -16,66 +16,54 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-############################
-## logging functions/vars ##
-############################
-BOLD="\e[1m"
-RESET="\e[0m"
-GREEN="\e[32m"
-BLUE="\e[34m"
-GRAY="\e[37m"
-RED="\e[31m"
+#############################
+## import common functions ##
+#############################
+location="$(dirname "${0}")"
+location="$(realpath "${location}")"
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
-success() {
- echo -e "$BOLD$GREEN>>>$RESET$BOLD $1$RESET"
-}
+source "${commonsh}"
-info() {
- echo -e "$BOLD$BLUE>>>$RESET$BOLD $1$RESET"
-}
-
-error() {
- echo -e "$BOLD$RED>>>$RESET$BOLD $1$RESET"
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
exit 1
-}
-
-####################
-## util functions ##
-####################
-check_ret() {
- if [ $? -ne 0 ]; then
- error "$1"
- fi
-}
+fi
#################
## main script ##
#################
if [ "$EUID" -ne 0 ]; then
error "You should run this script as root"
+ exit 1
fi
if [ $# -eq 0 ]; then
error "Please specify a name for the archive"
+ exit 1
fi
-NAME="$1"
-TARGET="$(realpath $1)"
-if [ -d $TARGET ]; then
+name="${1}"
+target="$(realpath "${1}")"
+
+if [ -d "${target}" ]; then
error "A directory with the specified archive name exists"
+ exit 1
fi
-mkdir $TARGET
+mkdir "${target}"
-if ! type mp > /dev/null; then
- error "mp is not installed, please install and configure mp"
+if ! type matt > /dev/null; then
+ error "matt is not installed, please install and configure matt"
+ exit 1
fi
info "Creating directory structure"
-pushd $TARGET > /dev/null
- mkdir -p {dev,proc,sys,run,tmp,root,home,boot,mnt}
- mkdir -p var/{log,mail,lib}
- mkdir -p usr/{bin,lib,sbin}
- mkdir -p etc/mp
+pushd "${target}" > /dev/null
+ install -Ddm755 {dev,proc,sys,run,tmp,root,home,boot,mnt}
+ install -Ddm755 var/{log,mail,lib}
+ install -Ddm755 usr/{bin,lib,sbin}
+ install -Ddm755 var/lib/matt
+ install -Ddm755 etc/matt
ln -sf usr/lib lib
ln -sf usr/lib lib64
@@ -126,25 +114,24 @@ EOF
EOF
popd > /dev/null
-export MP_ROOT="$TARGET" MP_YES=1
- info "Syncing repositories"
- mp-sync
- check_ret "mp-sync command failed"
+info "Syncing repositories"
+matt sync --root "${target}" --yes
+check_ret "matt command failed"
- info "Installing base system packages"
- mp-install acl attr coreutils binutils \
- bash e2fsprogs udev file release \
- findutils gawk grep gzip iana-etc \
- inetutils intltool iproute kmod less \
- openssl sed shadow tar tcl mandb \
- man-pages tzdata util-linux which \
- mp gettext iproute procps psmisc \
- mandb kbd dbus vim nano libxml2
- check_ret "mp-install command failed"
-unset MP_ROOT MP_YES
+info "Installing base system packages"
+matt install --root "${target}" --yes \
+ acl attr coreutils binutils \
+ bash e2fsprogs udev file release \
+ findutils gawk grep gzip iana-etc \
+ inetutils intltool iproute kmod less \
+ openssl sed shadow tar tcl mandb \
+ man-pages tzdata util-linux which \
+ matt gettext iproute procps psmisc \
+ mandb kbd dbus vim nano libxml2
+check_ret "matt command failed"
success "Installed the base system"
-cat > $TARGET/etc/inputrc << "EOF"
+cat > "${target}/etc/inputrc" << "EOF"
# do not bell on tab-completion
#set bell-style none
@@ -183,24 +170,24 @@ $if mode=emacs
$endif
EOF
-cat > $TARGET/etc/shells << "EOF"
+cat > "${target}/etc/shells" << "EOF"
/bin/sh
/bin/bash
EOF
-cp "$TARGET/etc/skel/."* "$TARGET/root"
+cp "${target}/etc/skel/."* "${target}/root"
info "Installing certs"
-wget -q https://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt -O "$TARGET/certdata.txt"
-matter-chroot $TARGET make-ca > /dev/null
+wget --show-progress -q https://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt -O "${target}/certdata.txt"
+matter-chroot "${target}" make-ca > /dev/null
check_ret "Failed to run make-ca, install certs manually"
-rm -f "$TARGET/certdata.txt"
+rm -f "${target}/certdata.txt"
info "Setup complete, now creating the archive..."
-pushd $TARGET > /dev/null
- tar czf ../${NAME}.tar.gz *
+pushd "${target}" > /dev/null
+ tar czf ../${name}.tar.gz *
check_ret "Failed to create the archive"
popd > /dev/null
success "Archive created, now cleaning up"
-rm -rf $TARGET && success "Build completed"
+rm -rf "${target}" && success "Build completed"
diff --git a/matter-chroot/Makefile b/matter-chroot/Makefile
new file mode 100644
index 0000000..59d1ab5
--- /dev/null
+++ b/matter-chroot/Makefile
@@ -0,0 +1,9 @@
+PREFIX = /usr
+
+install:
+ install -m755 "main.sh" $(DESTDIR)/$(PREFIX)/bin/matter-chroot
+
+uninstall:
+ rm $(DESTDIR)/$(PREFIX)/lib/matter-chroot
+
+.PHONY: install uninstall
diff --git a/matter-chroot/main.sh b/matter-chroot/main.sh
old mode 100644
new mode 100755
index 70b2901..754c619
--- a/matter-chroot/main.sh
+++ b/matter-chroot/main.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# matter-chroot | Matterlinux Chroot Script
+# matter-chroot | MatterLinux chroot script
# MatterLinux 2023-2024 (https://matterlinux.xyz)
# This program is free software: you can redistribute it and/or modify
@@ -16,67 +16,71 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-############################
-## logging functions/vars ##
-############################
-RED="\e[31m"
-BOLD="\e[1m"
-RESET="\e[0m"
+#############################
+## import common functions ##
+#############################
+location="$(dirname "${0}")"
+location="$(realpath "${location}")"
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
-error() {
- echo -e "$BOLD$RED>>>$RESET$BOLD $1$RESET"
+source "${commonsh}"
+
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
exit 1
-}
+fi
####################
## util functions ##
####################
linkresolv(){
- if [ ! -f "$TARGET/etc/resolv.conf" ]; then
- ln -sf /run/systemd/resolve/resolv.conf "$TARGET/etc/resolv.conf"
+ if [ ! -f "${target}/etc/resolv.conf" ]; then
+ ln -sf /run/systemd/resolve/resolv.conf "${target}/etc/resolv.conf"
fi
}
chrt() {
- mount -t proc proc "$TARGET/proc"
- mount -t sysfs sysfs "$TARGET/sys"
- if [[ -d "$TARGET/sys/firmware/efi/efivars" ]]; then
- mount -t efivarfs efivarfs "$TARGET/sys/firmware/efi/efivars"
+ mount -t proc proc "${target}/proc"
+ mount -t sysfs sysfs "${target}/sys"
+ if [[ -d "${target}/sys/firmware/efi/efivars" ]]; then
+ mount -t efivarfs efivarfs "${target}/sys/firmware/efi/efivars"
fi
- mount -o bind /dev "$TARGET/dev"
- mount -t devpts none "$TARGET/dev/pts"
- mount --bind /run "$TARGET/run"
+ mount -o bind /dev "${target}/dev"
+ mount -t devpts none "${target}/dev/pts"
+ mount --bind /run "${target}/run"
linkresolv
- if [ -h $TARGET/dev/shm ]; then
- mkdir -p $TARGET/$(readlink $TARGET/dev/shm)
+ if [ -h "${target}/dev/shm" ]; then
+ mkdir -p "${target}/$(readlink "${target}/dev/shm")"
else
- mount -t tmpfs -o nosuid,nodev tmpfs "$TARGET/dev/shm"
+ mount -t tmpfs -o nosuid,nodev tmpfs "${target}/dev/shm"
fi
local prompt='\['$BOLD'\['$RED'(chroot)\['$RESET'\['$BOLD' \u@\h:\w#\['$RESET' '
- chroot "$TARGET" /usr/bin/env -i \
- HOME=/root \
- TERM="$TERM" \
- PS1="$prompt" \
- PATH=/usr/bin:/usr/sbin \
+ chroot "${target}" /usr/bin/env -i \
+ HOME=/root \
+ TERM="${TERM}" \
+ PS1="${prompt}" \
+ PATH=/usr/bin:/usr/sbin \
"$@"
- RET_CODE=$?
+ local ret_code=$?
# kill procs that may prevent umount
killall -9 dirmngr 2> /dev/null
killall -9 gpg-agent 2> /dev/null
- umount "$TARGET/proc"
- mountpoint -q "$TARGET/sys/firmware/efi/efivars" && umount "$TARGET/sys/firmware/efi/efivars"
- umount "$TARGET/sys"
+ umount "${target}/proc"
+ mountpoint -q "${target}/sys/firmware/efi/efivars" && umount "${target}/sys/firmware/efi/efivars"
+ umount "${target}/sys"
- umount "$TARGET/dev/pts"
- mountpoint -q "$TARGET/dev/shm" && umount "$TARGET/dev/shm"
- umount "$TARGET/dev"
- umount "$TARGET/run"
+ umount "${target}/dev/pts"
+ mountpoint -q "${target}/dev/shm" && umount "${target}/dev/shm"
+ umount "${target}/dev"
+ umount "${target}/run"
+
+ return $ret_code
}
#################
@@ -84,24 +88,29 @@ chrt() {
#################
if [ "$EUID" -ne 0 ]; then
error "Cannot chroot without root"
+ exit 1
fi
if [ $# -eq 0 ]; then
error "Please specify a directory"
+ exit 1
fi
-TARGET=$(realpath $1)
-if [ -f $TARGET ]; then
- error "$TARGET is a file"
+target="$(realpath "${1}")"
+
+if [ -f "${target}" ]; then
+ error "${target} is a file"
+ exit 1
fi
-if [ ! -d $TARGET ]; then
- error "$TARGET does not exist"
+if [ ! -d "${target}" ]; then
+ error "${target} does not exist"
+ exit 1
fi
if [ $# -gt 1 ]; then
chrt ${@:2}
- exit $RET_CODE
+ exit $?
fi
chrt bash --noprofile --login
diff --git a/matter-iso/Makefile b/matter-iso/Makefile
new file mode 100644
index 0000000..ae0aa6d
--- /dev/null
+++ b/matter-iso/Makefile
@@ -0,0 +1,9 @@
+PREFIX = /usr
+
+install:
+ install -m755 "main.sh" $(DESTDIR)/$(PREFIX)/bin/matter-iso
+
+uninstall:
+ rm $(DESTDIR)/$(PREFIX)/lib/matter-iso
+
+.PHONY: install uninstall
diff --git a/matter-iso/README.md b/matter-iso/README.md
index f54ee37..a6f7fa0 100644
--- a/matter-iso/README.md
+++ b/matter-iso/README.md
@@ -8,4 +8,4 @@ a configuration directory:
```
matter-iso matterlinux_24.00.tar.gz isocfg
```
-To learn more about the configuration, see the [wiki page for releases](/wiki/release).
+To learn more about the configuration, see the [wiki page for releases](/wiki/releases).
diff --git a/matter-iso/main.sh b/matter-iso/main.sh
index 4f25491..0114f6f 100755
--- a/matter-iso/main.sh
+++ b/matter-iso/main.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# matter-iso | MatterLinux ISO Build Script
+# matter-iso | MatterLinux ISO build script
# MatterLinux 2023-2024 (https://matterlinux.xyz)
# This program is free software: you can redistribute it and/or modify
@@ -16,71 +16,35 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-############################
-## logging functions/vars ##
-############################
-BOLD="\e[1m"
-RESET="\e[0m"
-GREEN="\e[32m"
-BLUE="\e[34m"
-GRAY="\e[37m"
-RED="\e[31m"
-LOG_PREFIX=">>>"
+#############################
+## import common functions ##
+#############################
+location="$(dirname "${0}")"
+location="$(realpath "${location}")"
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
-echo_color() {
- echo -e "${1}"
-}
+source "${commonsh}"
-success() {
- echo_color "${BOLD}${GREEN}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
-}
-
-info() {
- echo_color "${BOLD}${BLUE}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
-}
-
-error() {
- echo_color "${BOLD}${RED}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
exit 1
-}
-
-errorne() {
- echo_color "${BOLD}${RED}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
-}
-
-print() {
- echo_color "${BOLD}${GRAY}$1${RESET}"
-}
-
-set_indent() {
- LOG_PREFIX="|>"
-}
-
-unset_indent() {
- LOG_PREFIX=">>>"
-}
+fi
####################
## util functions ##
####################
-check_ret() {
- if [ $? -ne 0 ]; then
- error "$1"
- fi
-}
-
check_retc() {
if [ $? -ne 0 ]; then
- errorne "$1"
+ error "${1}"
clean_tmpdir
exit 1
fi
}
clean_tmpdir(){
- if [ -d $TMPDIR ]; then
+ if [ -d "${tmpdir}" ]; then
info "Cleaning up temp directory"
- rm -rf $TMPDIR
+ rm -rf "${tmpdir}"
fi
}
@@ -101,61 +65,71 @@ check_iso_vars() {
#################
if [ "$EUID" -ne 0 ]; then
error "You should run this script as root"
+ exit 1
fi
if [ $# -ne 2 ]; then
error "Please specify a release archive and a config directory"
+ exit 1
fi
-ARCHIVE="$(realpath $1)"
-if [ ! -f $ARCHIVE ]; then
+archive="$(realpath "${1}")"
+
+if [ ! -f "${archive}" ]; then
error "Archive file not found"
+ exit 1
fi
-if [[ "$(file $ARCHIVE)" != *"gzip compressed data"* ]]; then
+if [[ "$(file "${archive}")" != *"gzip compressed data"* ]]; then
error "Bad archive format"
+ exit 1
fi
-CONFDIR="$(realpath $2)"
-if [ ! -d $CONFDIR ]; then
+confdir="$(realpath "${2}")"
+
+if [ ! -d "${confdir}" ]; then
error "Config directory not found"
+ exit 1
fi
-TMPDIR="${CONFDIR}_tmp"
-DISTDIR="${CONFDIR}/dist"
-ROOTDIR="${DISTDIR}/root"
-ISOSH="${TMPDIR}/iso.sh"
+tmpdir="${confdir}_tmp"
+distdir="${confdir}/dist"
+rootdir="${distdir}/root"
+isoh="${tmpdir}/iso.sh"
-mkdir -p $ROOTDIR
+mkdir -p "${rootdir}"
success "Created root and dist directory"
info "Copying over the config directory"
-cp -r $CONFDIR $TMPDIR
+cp -r "${confdir}" "${tmpdir}"
check_ret "Copy failed"
-if [ ! -f $ISOSH ]; then
+if [ ! -f "${isoh}" ]; then
error "ISO script not found"
+ exit 1
fi
-source $ISOSH
+source "${isoh}"
check_retc "Cannot source the ISO script"
+
check_iso_vars
check_retc "ISO script is not valid"
success "Sourced the ISO script"
info "Removing excluded files"
-rm -rf "$TMPDIR/dist"
+rm -rf "${tmpdir}/dist"
set_indent
for e in "${EXCLUDE[@]}"; do
- info "Removing $e"
- rm -rf "$TMPDIR/$e"
+ info "Removing ${e}"
+ rm -rf "${tmpdir}/${e}"
done
- rm -rf "$TMPDIR/.git"
+ rm -rf "${tmpdir}/.git"
unset_indent
info "Extracting release archive"
SECONDS=0
-tar --skip-old-files -xf "$ARCHIVE" -C "$TMPDIR"
+
+tar --skip-old-files -xf "${archive}" -C "${tmpdir}"
check_retc "Extract failed"
success "Extracted in ${SECONDS}s"
@@ -184,45 +158,45 @@ for p2 in "${PKGS2[@]}"; do
done
info "Adding public keys"
-matter-chroot "$TMPDIR" gpg --receive-keys $keys_str
+matter-chroot "${tmpdir}" gpg --receive-keys $keys_str
check_retc "Failed to add public keys"
if [ ! -z "${PKGS1}" ]; then
info "Installing extra packages (1)"
- matter-chroot "$TMPDIR" mp-sync
+ matter-chroot "${tmpdir}" matt sync
check_retc "Sync failed"
- matter-chroot "$TMPDIR" MP_YES=1 mp-install $pkgs1_str
+ matter-chroot "${tmpdir}" matt install --yes $pkgs1_str
check_retc "Install failed"
fi
info "Running build script"
-echo "source /iso.sh && build" > "$TMPDIR/stager.sh"
-matter-chroot "$TMPDIR" chmod +x /stager.sh
-matter-chroot "$TMPDIR" /stager.sh
+echo "source /iso.sh && build" > "${tmpdir}/stager.sh"
+matter-chroot "${tmpdir}" chmod +x /stager.sh
+matter-chroot "${tmpdir}" /stager.sh
check_ret "Build script failed"
-rm "$TMPDIR/stager.sh"
+rm "${tmpdir}/stager.sh"
info "Cleaning up and building initrd"
-rm "$ISOSH"
+rm "${isoh}"
pushd "$TMPDIR" > /dev/null
- mkdir -p "$ROOTDIR/boot"
- find . | cpio --quiet -H newc -o | xz -T0 --check=crc32 > "$ROOTDIR/boot/initrd.img"
+ mkdir -p "${rootdir}/boot"
+ find . | cpio --quiet -H newc -o | xz -T0 --check=crc32 > "${rootdir}/boot/initrd.img"
check_ret "Failed to build initrd"
popd > /dev/null
if [ ! -z "${PKGS2}" ]; then
info "Installing extra packages (2)"
- matter-chroot "$TMPDIR" MP_YES=1 mp-install $pkgs2_str
+ matter-chroot "${tmpdir}" MP_YES=1 matt install --yes $pkgs2_str
check_ret "Install failed"
fi
info "Copying over the bootdir"
-cp -r "$TMPDIR/boot"/* "$ROOTDIR/boot"
+cp -r "${tmpdir}/boot"/* "${rootdir}/boot"
info "Building the ISO..."
-pushd "$DISTDIR" > /dev/null
- grub-mkrescue -o "$DISTDIR/${NAME}_${VERSION}.iso" root
+pushd "${distdir}" > /dev/null
+ grub-mkrescue -o "${distdir}/${NAME}_${VERSION}.iso" root
check_retc "grub-mkrescue failed"
popd > /dev/null
diff --git a/matter-mirror/.gitignore b/matter-mirror/.gitignore
deleted file mode 100644
index 65e3ba2..0000000
--- a/matter-mirror/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-test/
diff --git a/matter-mirror/README.md b/matter-mirror/README.md
deleted file mode 100644
index c4919a8..0000000
--- a/matter-mirror/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# matter-mirror
-A simple python script to create and manage MatterLinux mirrors.
-**Does not support FTP!**
-
-### Usage
-To use the `matter-mirror` script, pass in a URL and a download (output)
-directory. For example:
-```bash
-mkdir base
-matter-mirror -u https://pkgs.matterlinux.xyz/base -o base
-```
-This will download the repo at `https://pkgs.matterlinux.xyz/base` to the
-`base` directory. Running it again, script will only download outdated or
-new packages.
diff --git a/matter-mirror/main.py b/matter-mirror/main.py
deleted file mode 100644
index ac91f66..0000000
--- a/matter-mirror/main.py
+++ /dev/null
@@ -1,262 +0,0 @@
-#!/bin/python3
-
-# matter-mirror | MatterLinux Repo Mirror Tool
-# MatterLinux 2023-2024 (https://matterlinux.xyz)
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-from os import path, chdir, listdir, remove
-from typing import List
-import requests as req
-import logging as log
-import configparser
-import argparse
-import tarfile
-import hashlib
-
-class BadResponse(Exception):
- def __init__(self, msg: str) -> None:
- super().__init__(f"Bad response: {msg}")
-
-class Pkg:
- def __init__(self, name: str, version: str, sum: str) -> None:
- self.archive = f"{name}_{version}.mpf"
- self.sig = f"{name}_{version}.mpf.sig"
-
- self.version = version
- self.name = name
- self.sum = sum
-
- def remove_old(self) -> None:
- files = listdir(".")
- for f in files:
- if f.startswith(f"{self.name}_"):
- remove(f)
-
-class Repo:
- def __init__(self, uri: str, out: str) -> None:
- self.pkgs: List[Pkg] = []
- self.author: str
- self.name: str
- self.pub: str
- self.uri = uri
- self.out = out
-
- def join_url(self, pth: str) -> str:
- if self.uri.endswith("/") and not pth.startswith("/"):
- return self.uri+pth
- elif self.uri.endswith("/") and pth.startswith("/"):
- return self.uri[:-1]+pth
- elif not self.uri.endswith("/") and pth.startswith("/"):
- return self.uri+pth
-
- return self.uri+"/"+pth
-
- def get_repo(self) -> None:
- repourl = self.join_url("repo")
- res = req.get(repourl)
-
- if res.status_code != 200:
- raise BadResponse(f"{res.status_code} - {repourl}")
-
- cfg = configparser.ConfigParser()
- cfg.read_string(res.content.decode("utf-8"))
-
- for k in cfg.keys():
- if k == "DEFAULT":
- continue
- self.name = k
-
- self.pub = cfg[self.name]["pub"]
- self.author = cfg[self.name]["author"]
-
- f = open("repo", "wb")
- f.write(res.content)
- f.close()
-
- def process_pkgs(self, pkgs: str) -> None:
- cfg = configparser.ConfigParser()
- cfg.read_string(pkgs)
-
- for k in cfg.keys():
- try:
- ver = cfg[k]["version"]
- sum = cfg[k]["sum"]
- except:
- continue
- self.pkgs.append(Pkg(k, ver, sum))
-
- def check_pkg(self, pkg: Pkg) -> bool:
- # true -> package is in the outdir and its up-to-date
- # false -> its not ^
- if not path.exists(pkg.archive) or not path.exists(pkg.sig):
- return False
-
- fhash = hashlib.sha256()
- f = open(pkg.archive, "rb")
-
- while chunk := f.read(8192):
- fhash.update(chunk)
-
- f.close()
- if pkg.sum != fhash.hexdigest():
- return False
-
- return True
-
- def check_pkgs(self) -> None:
- pkgcl = []
- for p in self.pkgs:
- pkgcl.append(p)
-
- for p in self.pkgs:
- if self.check_pkg(p):
- pkgcl.remove(p)
-
- self.pkgs = pkgcl
-
- def get_pkglist(self) -> None:
- arcname = f"{self.name}.tar.gz"
- pkgsurl = self.join_url(arcname)
- res = req.get(pkgsurl)
-
- if res.status_code != 200:
- raise BadResponse(f"{res.status_code} - {pkgsurl}")
-
- f = open(arcname, "wb")
- f.write(res.content)
- f.close()
-
- t = tarfile.open(arcname)
- for m in t.getmembers():
- if m.name != "pkgs":
- continue
-
- f = t.extractfile(m)
- if f == None: continue
- self.process_pkgs(f.read().decode("utf-8"))
- f.close()
- t.close()
-
- def download_pkg(self, p: Pkg) -> bool:
- p.remove_old()
-
- arcurl = self.join_url(p.archive)
- sigurl = self.join_url(p.sig)
-
- arcres = req.get(arcurl)
- sigres = req.get(sigurl)
-
- if arcres.status_code != 200:
- raise BadResponse(f"{arcres.status_code} - {arcurl}")
-
- if sigres.status_code != 200:
- raise BadResponse(f"{sigres.status_code} - {sigurl}")
-
- arcf = open(p.archive, "wb")
- arcf.write(arcres.content)
- arcf.close()
-
- sigf = open(p.sig, "wb")
- sigf.write(sigres.content)
- sigf.close()
-
- return True
-
-if __name__ == "__main__":
- log.basicConfig(
- format="[%(levelname)s] [%(asctime)s]: %(message)s",
- datefmt="%H:%M:%S",
- level=log.INFO
- )
-
- parser = argparse.ArgumentParser(
- prog="matter-mirror",
- description="Create and manage MatterLinux mirrors",
- epilog="Part of matter-tools | https://git.matterlinux.xyz/matter/matter-tools")
-
- parser.add_argument("-u", help="Repo URI", required=True, dest="uri")
- parser.add_argument("-o", help="Download directory", required=True, dest="out")
- args = parser.parse_args()
-
- if not args.uri.startswith("http://") and not args.uri.startswith("https://"):
- log.error(f"Bad URI: {args.uri}")
- exit(1)
-
- if not path.exists(args.out):
- log.error(f"Out directory not found: {args.out}")
- exit(1)
-
- if not path.isdir(args.out):
- log.error(f"Out directory is not a directory: {args.out}")
- exit(1)
-
- try:
- chdir(args.out)
- except Exception as e:
- log.error(f"Cannot change dir: {args.out}")
- exit(1)
-
- try:
- repo = Repo(args.uri, args.out)
- repo.get_repo()
- except Exception as e:
- log.error(e)
- exit(1)
-
- log.info(f"Got repo file => {repo.name}:{repo.author}:{repo.pub}")
- log.info("Downloading package list")
-
- try:
- repo.get_pkglist()
- except Exception as e:
- log.error(e)
- exit(1)
-
- all = len(repo.pkgs)
- if all == 0:
- log.error("Got no valid packages!")
- exit(1)
-
- log.info(f"Got total of {all} packages")
-
- try:
- repo.check_pkgs()
- except Exception as e:
- log.error(e)
- exit(1)
-
- old = len(repo.pkgs)
- if old == 0:
- log.info("All packages are up-to-date!")
- exit()
-
- print(f" Up-to-date packages: {all-old} ({int(100*(all-old)/all)}%)")
- print(f" New packages: {old} ({int(100*old/all)}%)")
-
- resc = 0
- for p in repo.pkgs:
- try:
- log.info(f"({repo.pkgs.index(p)+1}/{len(repo.pkgs)}) Downloading {p.name}")
- try:
- repo.download_pkg(p)
- except KeyboardInterrupt:
- log.error("Stopping downloads")
- exit(1)
- resc += 1
- except Exception as e:
- log.error(f"Download failed: {e}")
- continue
-
- log.info(f"Downloaded {resc} out of {old} packages ({int(100*resc/old)}%)")
diff --git a/mp-build/Makefile b/mp-build/Makefile
new file mode 100644
index 0000000..e83ec97
--- /dev/null
+++ b/mp-build/Makefile
@@ -0,0 +1,16 @@
+SCRIPTS = $(patsubst scripts/%.sh,%,$(wildcard scripts/*.sh))
+PREFIX = /usr
+
+install:
+ @for s in $(SCRIPTS) ; do \
+ echo "installing script: $$s" ; \
+ install -m755 "scripts/$$s.sh" $(DESTDIR)/$(PREFIX)/bin/$$s ; \
+ done
+
+uninstall:
+ @for s in $(SCRIPTS) ; do \
+ echo "removing script: $$s" ; \
+ rm $(DESTDIR)/$(PREFIX)/bin/$$s ; \
+ done
+
+.PHONY: install uninstall
diff --git a/mp-build/README.md b/mp-build/README.md
new file mode 100644
index 0000000..b896f8a
--- /dev/null
+++ b/mp-build/README.md
@@ -0,0 +1,26 @@
+# mp-build | MatterLinux package build scripts
+The package build scripts for MatterLinux package system. These scripts
+are used for building and creating packages.
+
+### Usage
+To create an package source directory, you can use the `mp-new`
+script:
+```bash
+mp-new _
+```
+This will create all the required source files, all templated
+according to the package name and the version you specify.
+
+After editing the source files, you can build the package by
+using the `mp-build` script:
+```bash
+mp-build /path/to/package
+```
+When the build is completed, the package archive will be created
+inside the `/path/to/package/dist` directory.
+
+You can also specify different build options, to list these
+options you can run:
+```bash
+mp-build --help
+```
diff --git a/mp-build/scripts/mp-build.sh b/mp-build/scripts/mp-build.sh
new file mode 100755
index 0000000..de85c68
--- /dev/null
+++ b/mp-build/scripts/mp-build.sh
@@ -0,0 +1,452 @@
+#!/bin/bash
+
+# mp-build | MatterLinux package build script
+# MatterLinux 2023-2024 (https://matterlinux.xyz)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+#############################
+## import common functions ##
+#############################
+location="$(dirname "${0}")"
+location="$(realpath "${location}")"
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
+
+source "${commonsh}"
+
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
+ exit 1
+fi
+
+####################
+## util functions ##
+####################
+# extracts the filename from an URL
+get_fn_url() {
+ file=$(echo "${1}" | rev | cut -d "/" -f -1 | rev)
+}
+
+# download/copy file, used for obtaning $FILES
+get_file() {
+ if [[ "${1}" == "https://"* || "${1}" == "http://"* || "${1}" == "ftp://"* ]]
+ then
+ curl "${1}" --progress-bar -OL
+ return $?
+ elif [ -f "${pkgpath}/${1}" ]; then
+ cp "${pkgpath}/${1}" .
+ return $?
+ else
+ return 1
+ fi
+}
+
+# length based hash check function
+check_hash() {
+ if [[ "$2" == "NOHASH" ]]; then
+ info "Using NOHASH for $1"
+ return 0
+ fi
+
+ local len=${#2}
+ if [[ $len == 128 ]]; then
+ local hsh=$(sha512sum "$1" | cut -d " " -f 1)
+ elif [[ $len == 64 ]]; then
+ local hsh=$(sha256sum "$1" | cut -d " " -f 1)
+ elif [[ $len == 64 ]]; then
+ local hsh=$(sha256sum "$1" | cut -d " " -f 1)
+ elif [[ $len == 40 ]]; then
+ local hsh=$(sha1sum "$1" | cut -d " " -f 1)
+ elif [[ $len == 32 ]]; then
+ local hsh=$(md5sum "$1" | cut -d " " -f 1)
+ fi
+
+ if [[ "$hsh" == "$2" ]]; then
+ success "Hash matches for $1"
+ return 0
+ else
+ error "Bad hash for $1"
+ return 1
+ fi
+}
+
+# prints the help info
+help_cmd() {
+ info "MatterLinux package build script"
+ info "Usage: ${0} [package directory]"
+ info "Options:"
+ echo_color " $BOLD--no-depend$RESET: don't check depends"
+ echo_color " $BOLD--no-stdout$RESET: disable stdout for PACKAGE() function"
+ echo_color " $BOLD--no-cache$RESET: don't check cache"
+ echo_color " $BOLD--no-opts$RESET: don't show/list options"
+ echo_color " $BOLD--cores$RESET: how many cores to use for the build"
+ echo
+ info "Licensed under GPLv3, see for more information"
+}
+
+# clean the this directory
+clean_dist() {
+ rm -f "${distpath}/DATA"
+ rm -f "${distpath}/CHANGES"
+ rm -f "${distpath}/INSTALL"
+ rm -f "${distpath}/HASHES"
+ rm -f "${distpath}/files.tar.gz"
+}
+
+# checks/installs a list of depends
+check_depends() {
+ local list=("$@")
+
+ if [ "${#list[@]}" == "0" ]; then
+ info "Got zero depends, skipping depend check"
+ return 0
+ fi
+
+ if [ "$EUID" -ne 0 ]; then
+ if type doas > /dev/null; then
+ DOAS="doas"
+ elif type sudo > /dev/null; then
+ DOAS="sudo"
+ else
+ error "Failed to find doas or sudo, skipping depend check"
+ return 0
+ fi
+ fi
+
+ for dep in "${list[@]}"; do
+ if [ -z "${depends_str}" ]; then
+ depends_str="${dep}"
+ else
+ depends_str="${depends_str} ${dep}"
+ fi
+ done
+
+ depends_uniq=$(echo "${depends_str}" | tr ' ' '\n' | sort | uniq)
+ depends_count=$(echo "${depends_uniq}" | wc -l)
+ depends_uniq=$(echo "${depends_uniq}" | tr '\n' ' ')
+
+ info "Installing ${depends_count} depends"
+ $DOAS matt install --yes $depends_uniq
+ return $?
+}
+
+#################
+## main script ##
+#################
+OPT_NO_DEPEND=0 # checking depends is ENABLED
+OPT_NO_STDOUT=0 # PACKAGE() function output is ENABLED
+OPT_NO_CACHE=0 # cache is ENABLED
+OPT_NO_OPTS=0 # showing/listing options is ENABLED
+OPT_CORES=$(nproc) # use ALL CPU cores
+
+# parses all the options
+for arg in "$@"; do
+ case $arg in
+ "--help")
+ help_cmd
+ exit 0
+ ;;
+ "--no-depend")
+ OPT_NO_DEPEND=1 ;;
+ "--no-stdout")
+ OPT_NO_STDOUT=1 ;;
+ "--no-cache")
+ OPT_NO_CACHE=1 ;;
+ "--no-opts")
+ OPT_NO_OPTS=1 ;;
+ "--cores"*)
+ OPT_CORES=$(echo "${arg}" | cut -d "=" -f2) ;;
+ --*)
+ error "Unknown option: ${arg}"
+ exit 1 ;;
+ *)
+ if [ -z "${TARGET}" ]; then
+ TARGET="${arg}"
+ else
+ error "Unknown argument: ${arg}"
+ exit 1
+ fi
+ ;;
+ esac
+done
+
+if [ -z "${TARGET}" ]; then
+ error "Package directory is not specified, run with \"--help\" for more information"
+ exit 1
+fi
+
+if [ ! -d "${TARGET}" ]; then
+ error "Package directory \"${TARGET}\" does not exist"
+ exit 1
+fi
+
+if [ $OPT_NO_DEPEND -eq 0 ] && ! command -v matt &> /dev/null; then
+ error "!!! BUILD ON MATTERLINUX !!!"
+ error "matt is not installed, please build on a MatterLinux system"
+ error "Do NOT create bug reports if build fails on non-MatterLinux systems"
+ info "Auto enabling NO_DEPEND as depend check will fail without matt"
+ OPT_NO_DEPEND=1
+fi
+
+# print the options
+if [ $OPT_NO_OPTS -eq 0 ]; then
+ info "Running mp-build with the options:"
+ print " $BOLD NO_DEPEND = $(itoyn $OPT_NO_DEPEND)"
+ print " $BOLD NO_SDTOUT = $(itoyn $OPT_NO_STDOUT)"
+ print " $BOLD NO_CACHE = $(itoyn $OPT_NO_CACHE)"
+ print " $BOLD NO_OPTS = $(itoyn $OPT_NO_OPTS)"
+ print " $BOLD CORES = $OPT_CORES"
+fi
+
+cd "${TARGET}"
+check_ret "Failed to change directory into \"${TARGET}\""
+
+if [ ! -f "pkg.sh" ]; then
+ error "Package directory does not contain a package script (pkg.sh)"
+ exit 1
+fi
+
+# source and verify the package script
+source "pkg.sh"
+check_ret "Failed to source the package script"
+
+check_pkg_vars
+check_ret
+
+# check the changes file
+if [ ! -f "changes.md" ]; then
+ warn "Package directory does not contain a changes file (changes.md)"
+ warn "Creating an empty one, however you should you should create an actual changes file"
+ echo "# ${VERSION}" > "changes.md"
+ echo "No changes specified" >> "changes.md"
+fi
+
+# setup package directories
+pkgpath="$(realpath .)"
+cachepath="$(realpath '.cache')"
+distpath="$(realpath 'dist')"
+rootpath="$(realpath 'root')"
+
+mkdir -p "${rootpath}"
+check_ret "Failed to create the root directory"
+
+# check the cache
+package_hash=$(md5sum "${pkgpath}/pkg.sh" 2> /dev/null | awk '{print $1}')
+changes_hash=$(md5sum "${pkgpath}/changes.md" 2> /dev/null | awk '{print $1}')
+
+if [ $OPT_NO_CACHE -eq 0 ] && [ -f "${cachepath}/last" ]; then
+ package_cache=$(sed -n '1p' "${cachepath}/last")
+ changes_cache=$(sed -n '2p' "${cachepath}/last")
+
+ if [[ "${package_cache}" == "${package_hash}" ]] && [[ "${changes_cache}" == "${changes_hash}" ]]; then
+ info "Found build in the cache (add --no-cache if you want to rebuild anyway)"
+ success "Build was successful"
+ exit 0
+ fi
+fi
+
+# check all the depends for the build
+all_depends+=("${DEPENDS[@]}")
+all_depends+=("${BUILD[@]}")
+
+if [ $OPT_NO_DEPEND -eq 0 ]; then
+ check_depends "${all_depends[@]}"
+ check_ret "Failed to check all the dependencies"
+fi
+
+# make sure file count and the hash count is the same
+file_count=${#FILES[@]}
+hash_count=${#HASHES[@]}
+
+if [[ $file_count != $hash_count ]]; then
+ error "There are ${file_count} files but ${hash_count} hashes"
+ exit 1
+fi
+
+# cleanup files from previous builds
+info "Cleaning up files from the previous build"
+set_indent
+
+for f in "${rootpath}"/*; do
+ # do not remove the file if its required for build
+ for ((i = 0; i < $file_count; i++)) do
+ get_fn_url "${FILES[i]}"
+ if [[ "$(realpath "${rootpath}/${file}")" == "$(realpath ${f})" ]]; then
+ isdownload=1
+ break
+ fi
+ done
+
+ if [ -z $isdownload ]; then
+ info "Removing file from previous build: $f"
+ rm -rf "$f"
+ fi
+
+ unset isdownload
+done
+
+unset_indent
+
+cd "${rootpath}"
+check_ret "Failed to change directory into the root directory"
+
+info "Obtaining all the files"
+set_indent
+
+for ((i = 0; i < $file_count; i++)) do
+ get_fn_url "${FILES[i]}"
+
+ # check if the file is already present
+ if [ -f "$file" ]; then
+ check_hash $file ${HASHES[i]} > /dev/null
+ if [ $? -eq 0 ]; then
+ success "($(($i+1))/$file_count) Using the file from previous build: $file"
+ continue
+ fi
+ rm -f $file
+ fi
+
+ info "($(($i+1))/$file_count) Obtaining file: $file"
+ get_file ${FILES[i]}
+ check_ret "Failed to obtain the file!"
+
+ check_hash "${file}" ${HASHES[i]}
+ check_ret "Verification failed for file: $file"
+done
+
+unset_indent
+
+info "Running the build function"
+export CFLAGS="-march=x86-64 -mtune=generic -O2"
+export ROOTDIR="${rootpath}"
+export MAKEFLAGS="-j${OPT_CORES}"
+export MAKEOPTS="-j${OPT_CORES}"
+export XORG_PREFIX="/usr"
+export XORG_CONFIG="--prefix=${XORG_PREFIX} --sysconfdir=/etc \
+ --localstatedir=/var --disable-static"
+
+SECONDS=0
+
+if [ $OPT_NO_STDOUT -eq 0 ]; then
+ fakeroot "${location}/mp-wrap" "../pkg.sh"
+ check_ret "Package PACKAGE() function failed"
+else
+ fakeroot "${location}/mp-wrap" "../pkg.sh" > /dev/null
+ check_ret "Package PACKAGE() function failed"
+fi
+
+unset XORG_CONFIG XORG_PREFIX
+unset CFLAGS ROOTDIR
+unset MAKEOPTS MAKEFLAGS
+
+if [ "$SECONDS" != "0" ]; then
+ success "Completed the build in ${SECONDS}s"
+else
+ success "Completed the build in less than a second"
+fi
+
+# remove all the $FILES
+for ((i = 0; i < $file_count; i++)) do
+ get_fn_url ${FILES[i]} && rm -f $file
+ success "Removed file: $file"
+done
+
+info "Building the package archive"
+set_indent
+
+# cleanup the dist directory
+mkdir -p "${distpath}"
+clean_dist
+
+# build the files archive
+find . -printf "%P\n" | fakeroot tar -czf "${distpath}/files.tar.gz" --no-recursion -T -
+check_ret "(1/6) Failed to create the files archive (files.tar.gz)"
+success "(1/6) Created the files archive (files.tar.gz)"
+
+# build the DATA file
+cat > "${distpath}/DATA" << EOF
+[${NAME}]
+version = ${VERSION}
+desc = ${DESC}
+size = $(du -sb "${rootpath}" | awk '{print $1}')
+EOF
+
+for dep in "${DEPENDS[@]}"; do
+ echo "depends = ${dep}" >> "${distpath}/DATA"
+done
+
+for keep in "${KEEP[@]}"; do
+ echo "keep = ${keep}" >> "${distpath}/DATA"
+done
+
+success "(2/6) Created the package data file (DATA)"
+
+# create the changes file
+cp "${pkgpath}/changes.md" "${distpath}/CHANGES"
+check_ret "(3/6) Failed to create the changes file (CHANGES)"
+success "(3/6) Created the changes file (CHANGES)"
+
+# create the install script
+if type INSTALL &>/dev/null; then
+ echo "$(type INSTALL | tail -n+2)" > "${distpath}/INSTALL"
+ check_ret "(4/6) Failed to create the install script (INSTALL)"
+fi
+success "(4/6) Created the install script (INSTALL)"
+
+# create the HASHES file
+find . -type f -exec md5sum {} >> "${distpath}/HASHES" \;
+check_ret "(5/6) Failed to create the file hash list (HASHES)"
+success "(5/6) Created the file hash list (HASHES)"
+
+# remove previous build archives
+for old in "${distpath}/${NAME}_"*.mpf; do
+ rm -f $old
+done
+
+# create the final archive
+archive="${NAME}_${VERSION}.mpf"
+pushd "${distpath}" > /dev/null
+ find . -printf "%P\n" | fakeroot tar -czf "${archive}" --no-recursion -T -
+ check_ret "(6/6) Failed to create the package archive (${archive})"
+popd > /dev/null
+success "(6/6) Created the package archive (${archive})"
+
+# clean up
+cd "${pkgpath}"
+
+info "Cleaning up the dist directory"
+clean_dist
+
+info "Cleaning the root directory"
+rm -rf "${rootpath}"
+
+# update the cache
+unset_indent
+info "Updating the package cache"
+set_indent
+
+mkdir -p "${cachepath}"
+
+echo "${package_hash}" > "${cachepath}/last"
+check_ret "(1/2) Failed to add package script to the cache"
+success "(1/2) Added package script to the cache"
+
+echo "${changes_hash}" >> "${cachepath}/last"
+check_ret "(2/2) Failed to add changes file to the cache"
+success "(2/2) Added changes file to the cache"
+
+unset_indent
+
+success "Build was successful"
+exit 0
diff --git a/mp-build/scripts/mp-migrate.sh b/mp-build/scripts/mp-migrate.sh
new file mode 100755
index 0000000..e12bc7d
--- /dev/null
+++ b/mp-build/scripts/mp-migrate.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+
+# mp-migrate | MatterLinux package migration script
+# MatterLinux 2023-2024 (https://matterlinux.xyz)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+#############################
+## import common functions ##
+#############################
+location="$(dirname "${0}")"
+location="$(realpath "${location}")"
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
+
+source "${commonsh}"
+
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
+ exit 1
+fi
+
+#################
+## main script ##
+#################
+if [ -z "$1" ]; then
+ error "Please specify a package directory"
+ exit 1
+fi
+
+if [ ! -d "$1" ]; then
+ error "Failed to access to the specified directory"
+ exit 1
+fi
+
+target="$(realpath "${1}")"
+pkg_script="${target}/pkg.sh"
+install_script="${target}/install.sh"
+
+if [ ! -f "${pkg_script}" ]; then
+ error "Specified directory does not contain a package script (pkg.sh)"
+ exit 1
+fi
+
+info "Sourcing the package script"
+source "${pkg_script}"
+
+if [ -z "${VERSION}" ]; then
+ error "Required package variable \"\$VERSION\" is not set"
+ exit 1
+fi
+
+info "Auto generating the changes file"
+cat > "${target}/changes.md" << EOF
+# ${VERSION}
+First version
+EOF
+
+info "Adding the gitignore file"
+cat > "${target}/.gitignore" << EOF
+.cache/
+dist/
+root/
+EOF
+
+sed -i 's/build() {/PACKAGE() {/' "${pkg_script}"
+check_ret "Failed to update the build function"
+
+if [ -f "${install_script}" ]; then
+ info "Migrating the install script"
+ echo >> "${pkg_script}"
+ echo "INSTALL(){" >> "${pkg_script}"
+
+ while read l; do
+ echo " ${l}" >> "${pkg_script}"
+ done < "${install_script}"
+
+ echo "}" >> "${pkg_script}"
+
+ rm "${install_script}"
+ check_ret "Failed to remove the install script"
+fi
+
+success "Migration is completed"
diff --git a/mp-build/scripts/mp-new.sh b/mp-build/scripts/mp-new.sh
new file mode 100755
index 0000000..435c3f3
--- /dev/null
+++ b/mp-build/scripts/mp-new.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+
+# mp-new | MatterLinux package creation script
+# MatterLinux 2023-2024 (https://matterlinux.xyz)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+#############################
+## import common functions ##
+#############################
+location="$(dirname "${0}")"
+location="$(realpath "${location}")"
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
+
+source "${commonsh}"
+
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
+ exit 1
+fi
+
+#################
+## main script ##
+#################
+if [ -z "$1" ]; then
+ error "Please specify a package"
+ exit 1
+fi
+
+pkg=$(basename "${1}")
+target=$(dirname "${1}")
+
+case "${1}" in
+ *_*)
+ name=$(echo "${pkg}" | cut -d "_" -f1)
+ version=$(echo "${pkg}" | cut -d "_" -f2)
+ ;;
+ *)
+ warn "Package version is not specified, using \"1\" as version instead"
+ name="${pkg}"
+ version="1"
+ ;;
+esac
+
+if [ -d "${target}/${name}" ]; then
+ error "There is already a directory for \"${target}/${name}\""
+ exit 1
+fi
+
+info "Creating directory for \"${name}\""
+
+mkdir "${target}/${name}"
+check_ret "Failed to create package directory for \"${name}\""
+
+cd "${target}/${name}"
+
+cat > pkg.sh << EOF
+# general info
+NAME="${name}"
+DESC=""
+VERSION="${version}"
+
+# required files
+FILES=()
+HASHES=()
+
+# install and build depends
+DEPENDS=()
+BUILD=()
+
+PACKAGE(){
+ tar xf "\${NAME}-\${VERSION}.tar.gz"
+ cd "\${NAME}-\${VERSION}"
+
+ # build commands
+
+ cd .. && rm -r "\${NAME}-\${VERSION}"
+}
+
+INSTALL(){
+ # install script
+ # remove if not requied
+}
+EOF
+
+cat > changes.md << EOF
+# ${version}
+First version
+EOF
+
+cat > .gitignore << EOF
+.cache/
+dist/
+root/
+EOF
+
+success "Created package directory and files for \"${name}\""
diff --git a/mp-build/scripts/mp-wrap.sh b/mp-build/scripts/mp-wrap.sh
new file mode 100755
index 0000000..8716af0
--- /dev/null
+++ b/mp-build/scripts/mp-wrap.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+# mp-wrap | MatterLinux package build function wrapper
+# MatterLinux 2023-2024 (https://matterlinux.xyz)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+#############################
+## import common functions ##
+#############################
+location="$(dirname "${0}")"
+location="$(realpath "${location}")"
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
+
+source "${commonsh}"
+
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
+ exit 1
+fi
+
+#################
+## main script ##
+#################
+if [ -z "${1}" ]; then
+ error "Package script not specified"
+ exit 1
+fi
+
+ninja(){
+ echo "[ninja wrapper] adding MAKEFLAGS"
+ /usr/bin/ninja $MAKEFLAGS $@
+}
+
+echo "running the PACKAGE() function"
+set -e
+
+source "${1}"
+PACKAGE
+ret="$?"
+
+set +e
+echo "PACKAGE() returned with code $ret"
+
+exit $ret
diff --git a/mp-pool/Makefile b/mp-pool/Makefile
new file mode 100644
index 0000000..e83ec97
--- /dev/null
+++ b/mp-pool/Makefile
@@ -0,0 +1,16 @@
+SCRIPTS = $(patsubst scripts/%.sh,%,$(wildcard scripts/*.sh))
+PREFIX = /usr
+
+install:
+ @for s in $(SCRIPTS) ; do \
+ echo "installing script: $$s" ; \
+ install -m755 "scripts/$$s.sh" $(DESTDIR)/$(PREFIX)/bin/$$s ; \
+ done
+
+uninstall:
+ @for s in $(SCRIPTS) ; do \
+ echo "removing script: $$s" ; \
+ rm $(DESTDIR)/$(PREFIX)/bin/$$s ; \
+ done
+
+.PHONY: install uninstall
diff --git a/mp-pool/README.md b/mp-pool/README.md
new file mode 100644
index 0000000..3c73d36
--- /dev/null
+++ b/mp-pool/README.md
@@ -0,0 +1,12 @@
+# mp-pool | MatterLinux pool build scripts
+The pool build scripts for MatterLinux package system. These scripts
+are used for building and creating pools.
+
+### Usage
+To build a pool from the source, you can use the `mp-pool`
+script:
+```bash
+mp-pool /path/to/pool
+```
+When the build is completed, the package archives and pool files
+will be created inside the `/path/to/pool/dist` directory.
diff --git a/mp-pool/scripts/mp-pool-clean.sh b/mp-pool/scripts/mp-pool-clean.sh
new file mode 100755
index 0000000..e57f662
--- /dev/null
+++ b/mp-pool/scripts/mp-pool-clean.sh
@@ -0,0 +1,126 @@
+#!/bin/bash
+
+# mp-pool-clean | MatterLinux pool cleanup script
+# MatterLinux 2023-2024 (https://matterlinux.xyz)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+#############################
+## import common functions ##
+#############################
+location=$(dirname "${0}")
+location=$(realpath "${location}")
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
+
+source "${commonsh}" > /dev/null
+
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
+ exit 1
+fi
+
+#################
+## main script ##
+#################
+target="${1}"
+
+if [ -z "${target}" ]; then
+ error "Please specify a pool directory"
+ exit 1
+fi
+
+if [ ! -d "${target}" ]; then
+ error "Pool directory \"${target}\" does not exist"
+ exit 1
+fi
+
+cd "${target}"
+check_ret "Failed to change directory into \"${target}\""
+
+if [ ! -f "pool.sh" ]; then
+ error "Package directory does not contain a pool script (pool.sh)"
+ exit 1
+fi
+
+# source and verify the package script
+source "pool.sh"
+check_ret "Failed to source the pool script"
+
+check_pool_vars
+check_ret
+
+# setup package directories
+pkgpath="$(realpath .)"
+distpath="$(realpath 'dist')"
+srcpath="$(realpath "${SRCDIR}")"
+
+if [ ! -d "${srcpath}" ]; then
+ error "Source path does not exist"
+ exit 1
+fi
+
+if [ ! -d "${distpath}" ]; then
+ info "Nothing to do (dist directory does not exist)"
+ exit 1
+fi
+
+# source and store every package
+files=("INFO" "LIST")
+pc="$(ls -1q "${srcpath}" | wc -l)"
+pi=1
+
+info "Sourcing all the packages"
+set_indent
+
+for pkg in "${srcpath}/"*; do
+ package=$(basename "${pkg}")
+ info "(${pi}/${pc}) Sourcing \"${package}\""
+
+ source "${pkg}/pkg.sh"
+ check_ret "(${pi}/${pc}) Failed to import the source script for \"${package}\""
+
+ check_pkg_vars
+ check_ret
+
+ files+=("${NAME}_${VERSION}.mpf")
+ files+=("${NAME}_${VERSION}.mpf.sig")
+ pi=$((pi+1))
+done
+
+success "Completed"
+unset_indent
+
+info "Cleaning up old archives and signatures"
+pushd "${distpath}" > /dev/null
+set_indent
+
+for file in *; do
+ found=0
+ for f in "${files[@]}"; do
+ if [ "${file}" == "${f}" ]; then
+ found=1
+ break
+ fi
+ done
+
+ if [ $found -eq 0 ]; then
+ info "Removing ${file}"
+ rm "${file}"
+ check_ret "Failed to remove ${file}"
+ fi
+done
+
+popd > /dev/null
+success "Completed"
+unset_indent
diff --git a/mp-pool/scripts/mp-pool.sh b/mp-pool/scripts/mp-pool.sh
new file mode 100755
index 0000000..b45fb9c
--- /dev/null
+++ b/mp-pool/scripts/mp-pool.sh
@@ -0,0 +1,293 @@
+#!/bin/bash
+
+# mp-pool | MatterLinux pool build script
+# MatterLinux 2023-2024 (https://matterlinux.xyz)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+#############################
+## import common functions ##
+#############################
+location=$(dirname "${0}")
+location=$(realpath "${location}")
+commonsh="$(echo "${location}" | sed 's/\/bin/\/lib/g')/mtsc-common.sh"
+
+source "${commonsh}" > /dev/null
+
+if [ "${?}" != "0" ]; then
+ echo "Failed to import mtsc-common"
+ exit 1
+fi
+
+####################
+## util functions ##
+####################
+# prints the help info
+help_cmd() {
+ info "MatterLinux pool build script"
+ info "Usage: ${0} [pool directory]"
+ info "Options:"
+ echo_color " $BOLD--skip-fail$RESET: skip if a package build fails"
+ echo_color " $BOLD--no-depend$RESET: don't check depends"
+ echo_color " $BOLD--no-stdout$RESET: disable stdout for build() function"
+ echo_color " $BOLD--no-cache$RESET: don't use cache"
+ echo_color " $BOLD--no-opts$RESET: don't show/list options"
+ echo_color " $BOLD--no-sign$RESET: don't sign build packages"
+ echo_color " $BOLD--cores$RESET: how many cores to use for the build"
+ echo
+ info "Licensed under GPLv3, see for more information"
+}
+
+# clean the dist directory
+clean_dist() {
+ rm -f "${distpath}/DATA"
+ rm -f "${distpath}/CHANGES"
+ rm -f "${distpath}/INSTALL"
+ rm -f "${distpath}/HASHES"
+ rm -f "${distpath}/files.tar.gz"
+}
+
+# convert bash array to newline splitted string
+list_to_str(){
+ local list=("$@")
+ for el in "${list[@]}"; do
+ if [ -z "${str}" ]; then
+ str="${el}"
+ else
+ printf -v str "${str}\n ${el}"
+ fi
+ done
+}
+
+# run mp-build with options
+mp_build_opts(){
+ local opts=("${1}" "--no-opts")
+
+ if [ $OPT_NO_DEPEND -eq 1 ]; then
+ opts+=("--no-depend")
+ fi
+
+ if [ $OPT_NO_STDOUT -eq 1 ]; then
+ opts+=("--no-stdout")
+ fi
+
+ if [ $OPT_NO_CACHE -eq 1 ]; then
+ opts+=("--no-cache")
+ fi
+
+ mp-build ${opts[@]}
+ return "$?"
+}
+
+#################
+## main script ##
+#################
+OPT_SKIP_FAIL=0 # stop build when a package build fails
+OPT_NO_DEPEND=0 # checking depends is ENABLED
+OPT_NO_STDOUT=0 # build() function output is ENABLED
+OPT_NO_CACHE=0 # cache is ENABLED
+OPT_NO_OPTS=0 # showing/listing options is ENABLED
+OPT_NO_SIGN=0 # sign all the built packages
+OPT_CORES=$(nproc) # use ALL CPU cores
+
+# parses all the options
+for arg in "$@"; do
+ case $arg in
+ "--help")
+ help_cmd
+ exit 0
+ ;;
+ "--skip-fail")
+ OPT_SKIP_FAIL=1 ;;
+ "--no-depend")
+ OPT_NO_DEPEND=1 ;;
+ "--no-stdout")
+ OPT_NO_STDOUT=1 ;;
+ "--no-cache")
+ OPT_NO_CACHE=1 ;;
+ "--no-opts")
+ OPT_NO_OPTS=1 ;;
+ "--no-sign")
+ OPT_NO_SIGN=1 ;;
+ "--cores"*)
+ OPT_CORES=$(echo "${arg}" | cut -d "=" -f2) ;;
+ --*)
+ error "Unknown option: ${arg}"
+ exit 1 ;;
+ *)
+ if [ -z "${TARGET}" ]; then
+ TARGET="${arg}"
+ else
+ error "Unknown argument: ${arg}"
+ exit 1
+ fi
+ ;;
+ esac
+done
+
+if [ -z "${TARGET}" ]; then
+ error "Pool directory is not specified, run with \"--help\" for more information"
+ exit 1
+fi
+
+if [ ! -d "${TARGET}" ]; then
+ error "Pool directory \"${TARGET}\" does not exist"
+ exit 1
+fi
+
+if [ $OPT_NO_DEPEND -eq 0 ] && ! command -v matt &> /dev/null; then
+ error "!!! BUILD ON MATTERLINUX !!!"
+ error "matt is not installed, please build on a MatterLinux system"
+ error "Do NOT create bug reports if build fails on non-MatterLinux systems"
+ info "Auto enabling NO_DEPEND as depend check will fail without mp"
+ OPT_NO_DEPEND=1
+fi
+
+# print the options
+if [ $OPT_NO_OPTS -eq 0 ]; then
+ info "Running mp-pool with the options:"
+ print " $BOLD SKIP_FAIL = $(itoyn $OPT_SKIP_FAIL)"
+ print " $BOLD NO_DEPEND = $(itoyn $OPT_NO_DEPEND)"
+ print " $BOLD NO_SDTOUT = $(itoyn $OPT_NO_STDOUT)"
+ print " $BOLD NO_CACHE = $(itoyn $OPT_NO_CACHE)"
+ print " $BOLD NO_OPTS = $(itoyn $OPT_NO_OPTS)"
+ print " $BOLD NO_SIGN = $(itoyn $OPT_NO_SIGN)"
+ print " $BOLD CORES = $OPT_CORES"
+fi
+
+cd "${TARGET}"
+check_ret "Failed to change directory into \"${TARGET}\""
+
+if [ ! -f "pool.sh" ]; then
+ error "Package directory does not contain a pool script (pool.sh)"
+ exit 1
+fi
+
+# source and verify the package script
+source "pool.sh"
+check_ret "Failed to source the pool script"
+
+check_pool_vars
+check_ret
+
+# setup package directories
+pkgpath="$(realpath .)"
+distpath="$(realpath 'dist')"
+srcpath="$(realpath "${SRCDIR}")"
+
+mkdir -p "${distpath}"
+check_ret "Failed to create the dist directory"
+
+if [ ! -d "${srcpath}" ]; then
+ error "Source path does not exist"
+ exit 1
+fi
+
+# build every package
+pc="$(ls -1q "${srcpath}" | wc -l)"
+pi=1
+
+for pkg in "${srcpath}/"*; do
+ package=$(basename "${pkg}")
+ info "(${pi}/${pc}) Building \"${package}\""
+
+ if [ $OPT_SKIP_FAIL -eq 1 ]; then
+ mp_build_opts "${pkg}"
+ if [ $? -ne "0" ]; then
+ error "(${pi}/${pc}) Build failed for \"${package}\", skipping"
+ pi=$((pi+1))
+ continue
+ fi
+ else
+ mp_build_opts "${pkg}"
+ check_ret "(${pi}/${pc}) Build failed for \"${package}\""
+ fi
+
+ archive="$(find "${pkg}/dist" -name "*.mpf" | tail -n1)"
+ name="$(echo "${archive}" | cut -d _ -f 1)"
+
+ if [ ! -z "${archive}" ]; then
+ rm -f "${distpath}/${name}_"*
+ mv "${archive}" "${distpath}"
+ check_ret "(${pi}/${pc}) Moving package archive failed for \"${package}\""
+ fi
+
+ success "(${pi}/${pc}) Build was successful for \"${package}\""
+ pi=$((pi+1))
+done
+
+success "Completed all the package builds"
+
+# sign packages
+if [ "$OPT_NO_SIGN" -eq 0 ]; then
+ gpg --list-secret-keys "${PUBKEY}" &> /dev/null
+ check_ret "Package signing is enabled, however you do not have the required private key"
+
+ info "Signing package archives"
+ set_indent
+
+ for pkg in "${distpath}/"*".mpf"; do
+ gpg --default-key "${PUBKEY}" --yes --detach-sign "${pkg}" &> /dev/null
+ check_ret "Failed to sign package archive: \"$(basename "${pkg}")\""
+ success "Signed archive: $(basename "${pkg}")"
+ done
+
+ success "Signing process was completed"
+ unset_indent
+fi
+
+info "Creating pool files"
+set_indent
+
+# create INFO file
+cat > "${distpath}/INFO" << EOF
+[${NAME}]
+size = $(du -sb "${distpath}" | awk '{print $1}')
+maintainer = ${MAINTAINER}
+pubkey = ${PUBKEY}
+EOF
+
+check_ret "(1/2) Failed to create pool info file (INFO)"
+success "(1/2) Created pool info file (INFO)"
+
+# create LIST archive
+rm -rf "${distpath}/list"
+mkdir -p "${distpath}/list"
+cd "${distpath}/list"
+
+check_ret "Failed change directory into temporary list directory"
+info "Creating package list archive"
+
+for pkg in "${distpath}/"*".mpf"; do
+ archive="$(basename "${pkg}")"
+ name="${archive::-4}"
+
+ mkdir "${name}"
+ check_ret "Failed to create list directory for \"${archive}\", is there two packages with the same name?"
+
+ tar xf "${pkg}" -C "${name}" DATA
+ check_ret "Failed to extract data file from \"${archive}\""
+done
+
+pushd "${distpath}/list" > /dev/null
+ tar czf "${distpath}/LIST" *
+ check_ret "(2/2) Failed to create list archive (LIST)"
+popd > /dev/null
+
+rm -r "${distpath}/list"
+check_ret "(2/2) Failed to remove temporary list directory"
+success "(2/2) Created package list archive (LIST)"
+unset_indent
+
+success "Pool build was successful"
diff --git a/mtsc-common/Makefile b/mtsc-common/Makefile
new file mode 100644
index 0000000..312d928
--- /dev/null
+++ b/mtsc-common/Makefile
@@ -0,0 +1,9 @@
+PREFIX = /usr
+
+install:
+ install -m755 "common.sh" $(DESTDIR)/$(PREFIX)/lib/mtsc-common.sh
+
+uninstall:
+ rm $(DESTDIR)/$(PREFIX)/lib/mtsc-common.sh
+
+.PHONY: install uninstall
diff --git a/mtsc-common/README.md b/mtsc-common/README.md
new file mode 100644
index 0000000..d7d1eb6
--- /dev/null
+++ b/mtsc-common/README.md
@@ -0,0 +1,3 @@
+# mtsc-common | MatterLinux common script functions
+A (bash) shell script that contains common functions used in MatterLinux
+build scripts and tools.
diff --git a/mtsc-common/common.sh b/mtsc-common/common.sh
new file mode 100755
index 0000000..8d26080
--- /dev/null
+++ b/mtsc-common/common.sh
@@ -0,0 +1,206 @@
+#!/bin/bash
+
+# mtsc-common | MatterLinux common script functions
+# MatterLinux 2023-2024 (https://matterlinux.xyz)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+$(return 0 2>/dev/null)
+
+if [ $? -eq 1 ]; then
+ echo "This script contains common functions for MatterLinux tools/scripts"
+ echo "You are not supposed to directly run it, now exiting to prevent any errors"
+ exit 1
+fi
+
+############################
+## logging functions/vars ##
+############################
+BOLD="\e[1m"
+RESET="\e[0m"
+YELLOW="\e[33m"
+GREEN="\e[32m"
+BLUE="\e[34m"
+GRAY="\e[37m"
+RED="\e[31m"
+
+NORMAL_PREFIX=">>>"
+INDENT_PREFIX=" |"
+
+LOG_PREFIX="$NORMAL_PREFIX"
+
+echo_color() {
+ echo -e "${1}"
+}
+
+success() {
+ if [ "$LOG_PREFIX" == "$NORMAL_PREFIX" ]; then
+ echo_color "${BOLD}${GREEN}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
+ else
+ echo_color "${BOLD}${GREEN}${LOG_PREFIX}${RESET} $1"
+ fi
+}
+
+info() {
+ if [ "$LOG_PREFIX" == "$NORMAL_PREFIX" ]; then
+ echo_color "${BOLD}${BLUE}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
+ else
+ echo_color "${BOLD}${BLUE}${LOG_PREFIX}${RESET} $1"
+ fi
+}
+
+warn() {
+ if [ "$LOG_PREFIX" == "$NORMAL_PREFIX" ]; then
+ echo_color "${BOLD}${YELLOW}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
+ else
+ echo_color "${BOLD}${YELLOW}${LOG_PREFIX}${RESET} $1"
+ fi
+}
+
+error() {
+ if [ "$LOG_PREFIX" == "$NORMAL_PREFIX" ]; then
+ echo_color "${BOLD}${RED}${LOG_PREFIX}${RESET}${BOLD} $1 ${RESET}"
+ else
+ echo_color "${BOLD}${RED}${LOG_PREFIX}${RESET} $1"
+ fi
+}
+
+print() {
+ echo_color "${BOLD}${GRAY}$1${RESET}"
+}
+
+set_indent() {
+ LOG_PREFIX="$INDENT_PREFIX"
+}
+
+unset_indent() {
+ LOG_PREFIX="$NORMAL_PREFIX"
+}
+
+####################
+## util functions ##
+####################
+check_ret() {
+ if [ $? -ne 0 ]; then
+ if [ ! -z "$1" ]; then
+ error "$1"
+ fi
+ exit 1
+ fi
+}
+
+# integer-to-yes-or-no
+itoyn() {
+ if [ $1 -eq 0 ]; then
+ echo "${RED}no${RESET}"
+ else
+ echo "${GREEN}yes${RESET}"
+ fi
+}
+
+# checks if all the required package vars/functions are set
+check_pool_vars() {
+ if [ ! -n "$NAME" ]; then
+ error "Failed to load the pool script"
+ set_indent
+
+ error "Required pool variable is not set: \"\$NAME\""
+ unset_indent
+
+ return 1
+ elif [ ! -n "$MAINTAINER" ]; then
+ error "Failed to load the pool script"
+ set_indent
+
+ error "Required pool variable is not set: \"\$MAINTAINER\""
+ unset_indent
+
+ return 1
+ elif [ ! -n "$PUBKEY" ]; then
+ error "Failed to load the pool script"
+ set_indent
+
+ error "Required pool variable is not set: \"\$PUBKEY\""
+ unset_indent
+
+ return 1
+ elif [ ! -n "$SRCDIR" ]; then
+ error "Failed to load the pool script"
+ set_indent
+
+ error "Required pool variable is not set: \"\$SRCDIR\""
+ unset_indent
+
+ return 1
+ fi
+
+ case "${NAME}" in
+ *" "*)
+ error "Pool name contains an invalid character: \" \""
+ unset_indent
+ return 1 ;;
+ esac
+
+ return 0
+}
+
+# checks if all the required package vars/functions are set
+check_pkg_vars() {
+ if [ ! -n "$NAME" ]; then
+ error "Failed to load the package script"
+ set_indent
+
+ error "Required package variable is not set: \"\$NAME\""
+ unset_indent
+
+ return 1
+ elif [ ! -n "$VERSION" ]; then
+ error "Failed to load the package script"
+ set_indent
+
+ error "Required package variable is not set: \"\$VERSION\""
+ unset_indent
+
+ return 1
+ elif [ ! -n "$DESC" ]; then
+ error "Failed to load the package script"
+ set_indent
+
+ error "Required package variable is not set: \"\$DESC\""
+ unset_indent
+
+ return 1
+ elif ! type PACKAGE &>/dev/null; then
+ error "Failed to load the package script"
+ set_indent
+
+ error "Required \"PACKAGE()\" function is not defined"
+ unset_indent
+
+ return 1
+ fi
+
+ case "${NAME}" in
+ *_*)
+ error "Package name contains an invalid character: \"_\""
+ unset_indent
+ return 1 ;;
+ *" "*)
+ error "Package name contains an invalid character: \" \""
+ unset_indent
+ return 1 ;;
+ esac
+
+ return 0
+}