new: mtsc-common, mp-build and mp-pool

This commit is contained in:
ngn 2024-08-11 17:45:54 +03:00
parent e9db1d41a5
commit aa5fbb82d6
26 changed files with 1619 additions and 478 deletions

View File

@ -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

View File

@ -1,6 +1,7 @@
# tools | Matterlinux Tools and Scripts Collection
# mtsc | MatterLinux tools and scripts collection
This repository contains different tools and scripts
for general matterlinux installation and configuration.
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)

9
matter-base/Makefile Normal file
View File

@ -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

View File

@ -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

115
matter-base/main.sh Normal file → Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
############################
## 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"

9
matter-chroot/Makefile Normal file
View File

@ -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

91
matter-chroot/main.sh Normal file → Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
############################
## 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

9
matter-iso/Makefile Normal file
View File

@ -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

View File

@ -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).

View File

@ -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 <https://www.gnu.org/licenses/>.
############################
## 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

View File

@ -1 +0,0 @@
test/

View File

@ -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.

View File

@ -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 <https://www.gnu.org/licenses/>.
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)}%)")

16
mp-build/Makefile Normal file
View File

@ -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

26
mp-build/README.md Normal file
View File

@ -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 <name>_<version>
```
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
```

452
mp-build/scripts/mp-build.sh Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
#############################
## 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} <options> [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 <https://www.gnu.org/licenses/> 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

94
mp-build/scripts/mp-migrate.sh Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
#############################
## 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"

108
mp-build/scripts/mp-new.sh Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
#############################
## 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}\""

56
mp-build/scripts/mp-wrap.sh Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
#############################
## 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

16
mp-pool/Makefile Normal file
View File

@ -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

12
mp-pool/README.md Normal file
View File

@ -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.

126
mp-pool/scripts/mp-pool-clean.sh Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
#############################
## 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

293
mp-pool/scripts/mp-pool.sh Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
#############################
## 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} <options> [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 <https://www.gnu.org/licenses/> 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"

9
mtsc-common/Makefile Normal file
View File

@ -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

3
mtsc-common/README.md Normal file
View File

@ -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.

206
mtsc-common/common.sh Executable file
View File

@ -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 <https://www.gnu.org/licenses/>.
$(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
}