Compare commits

...

11 Commits

6 changed files with 291 additions and 100 deletions

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2024 CapCreeperGR Copyright (c) 2024 EnumDev
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -9,20 +9,19 @@ BPM Utils is a package providing a number of different helper scripts for settin
## Provided Scripts ## Provided Scripts
- bpm-setup (Creates a directory with the required files for a BPM package) - bpm-setup (Creates a directory with the required files for a BPM package)
- bpm-package (Turns a BPM package directory into a .bpm archive) - bpm-package (Turns a BPM package directory into a .bpm archive)
- bpm-convert (Converts source packages to binary ones)
- create-repository-data (Generates a repository package data list for unpac)
## Installation ## Installation
Currently all BPM Utilities are simple bash scripts. This means you are able to simply clone this repository and place these scripts wherever you would like. Additionally pre-made packages are available for the following package managers: \ Currently all BPM Utilities are simple bash scripts. This means you are able to simply clone this repository and place these scripts wherever you would like
BPM: https://gitlab.com/bubble-package-manager/bpm-utils-bpm \
Pacman: https://gitlab.com/bubble-package-manager/bpm-utils-pacman
## Package Creation using BPM Utils ## Package Creation using BPM Utils
Creating a package for BPM with these utilities is simple Creating a package for BPM with these utilities is simple
2) Run the following command (You can run the comamnd with no arguments to see available options) 2) Run the following command (You can run the comamnd with no arguments to see available options)
``` ```
bpm-setup -D my_bpm_package -t <binary/source> bpm-setup -D my_package -t <binary/source>
``` ```
3) This will create a directory named 'my_bpm_package' under the current directory with all the required files for the chosen package type 3) This will create a directory named 'my_bpm_package' under the current directory with all the required files for the chosen package type
4) You are able to edit the pkg.info descriptor file inside the newly created directory to your liking. Here's an example of what a descriptor file could look like 4) You are able to edit the pkg.info descriptor file inside the newly created directory to your liking. Here's an example of what a descriptor file could look like
@ -30,12 +29,14 @@ bpm-setup -D my_bpm_package -t <binary/source>
name: my_package name: my_package
description: My package's description description: My package's description
version: 1.0 version: 1.0
revision: 2 (Optional)
architecture: x86_64 architecture: x86_64
url: https://www.my-website.com/ (Optional) url: https://www.my-website.com/ (Optional)
license: MyLicense (Optional) license: MyLicense (Optional)
type: <binary/source> type: <binary/source>
depends: dependency1,dependency2 (Optional) depends: ["dependency1","dependency2"] (Optional)
make_depends: make_depend1,make_depend2 (Optional) optional_depends: ["optional_depend1","optional_depend2"]
make_depends: ["make_depend1","make_depend2"] (Optional)
``` ```
### Binary Packages ### Binary Packages
3) If you are making a binary package, copy all your binaries along with the directories they reside in (i.e files/usr/bin/my_binary) 3) If you are making a binary package, copy all your binaries along with the directories they reside in (i.e files/usr/bin/my_binary)

View File

@ -1,10 +1,17 @@
#!/bin/bash #!/bin/bash
while getopts "ksa:" o; do if [ -f .compilation-options ]; then
source ./.compilation-options
fi
echo "$ARCH"
while getopts "ksfa:" o; do
case "${o}" in case "${o}" in
a) ARCH="$OPTARG";; a) ARCH="$OPTARG";;
k) KEEP=true;; k) KEEP=true;;
s) SKIPCHECK=true;; s) SKIPCHECK=true;;
f) FORCE=true;;
*) exit 1;; *) exit 1;;
esac esac
done done
@ -20,7 +27,7 @@ if ! [ -f "$PACKAGE" ]; then
echo "$PACKAGE is not a path to a file" echo "$PACKAGE is not a path to a file"
exit 1 exit 1
fi fi
if ! file "$PACKAGE" | grep -q 'gzip compressed data'; then if ! file "$PACKAGE" | grep -q 'POSIX tar archive'; then
echo "$PACKAGE is not a BPM package" echo "$PACKAGE is not a BPM package"
exit 1 exit 1
fi fi
@ -30,30 +37,97 @@ if ! tar -tf "$PACKAGE" | grep -q 'source.sh'; then
fi fi
echo "$Converting $PACKAGE..." echo "$Converting $PACKAGE..."
PKGINFO_FILE=$(tar -axf "$PACKAGE" pkg.info -O)
declare -A PKGINFO declare -A PKGINFO
# Declare and run Read Package Information function
function ReadPkgInfo() {
local BACK="$PWD"
cd "$DIR"
if [ $# -eq 0 ]; then
FILE=pkg.info
PKGINFO_FILE=$(tar -xf "$PACKAGE" pkg.info -O)
else
FILE=pkg.info."$1"
fi
if ! tar -tf "$PACKAGE" "$FILE"; then
echo "Could not find $FILE in $PACKAGE"
exit 1
fi
PKGINFO_FILE=$(tar -xf "$PACKAGE" "$FILE" -O)
while read line; do while read line; do
PKGINFO[$(echo -n "$line" | cut -d":" -f1 | xargs)]=$(echo -n "$line" | cut -d":" -f2 | xargs) PKGINFO[$(echo -n "$line" | cut -d":" -f1 | xargs)]=$(echo -n "$line" | cut -d":" -f2 | xargs)
done < <(tar -axf "$PACKAGE" pkg.info -O) done < <(tar -xf "$PACKAGE" "$FILE" -O)
cd "$BACK"
}
ReadPkgInfo
if [ -z "$FORCE" ] && command -v bpm &> /dev/null && [ -n "$PKGINFO[depends]" ]; then
MISSING=()
for depend in $(echo "${PKGINFO[depends]}" | tr -d '[]' | tr ',' '\n' ); do
if ! bpm info "$depend" &> /dev/null; then
MISSING+=("$depend")
fi
done
if [ "${#MISSING[@]}" -ne 0 ]; then
echo "The following dependencies could not be resolved: ${MISSING[@]}"
EXIT=true
fi
elif ! command -v bpm &> /dev/null; then
echo "BPM not in PATH. Skipping dependency resolution"
elif [ -n "$FORCE" ]; then
echo "Force compilation enabled. Skipping dependency resolution"
fi
if [ -z "$FORCE" ] && command -v bpm &> /dev/null && [ -n "$PKGINFO[make_depends]" ]; then
MISSING=()
for depend in $(echo "${PKGINFO[make_depends]}" | tr -d '[]' | tr ',' '\n' ); do
if ! bpm info "$depend" &> /dev/null; then
MISSING+=("$depend")
fi
done
if [ "${#MISSING[@]}" -ne 0 ]; then
echo "The following make dependencies could not be resolved: ${MISSING[@]}"
EXIT=true
fi
elif ! command -v bpm &> /dev/null; then
echo "BPM not in PATH. Skipping make dependency resolution"
elif [ -n "$FORCE" ]; then
echo "Force compilation enabled. Skipping make dependency resolution"
fi
if [ -n "$EXIT" ]; then
exit 1
fi
# Creating temporary compilation directory structure
TEMPDIR="/var/tmp/bpm_source_${PKGINFO[name]}" TEMPDIR="/var/tmp/bpm_source_${PKGINFO[name]}"
if [ -d "$TEMPDIR" ] && [ -z "$KEEP" ]; then if [ -d "$TEMPDIR" ] && [ -z "$KEEP" ]; then
rm -rf "$TEMPDIR" rm -rf "$TEMPDIR"
fi fi
mkdir -p "$TEMPDIR" mkdir -p "$TEMPDIR"
mkdir -p "$TEMPDIR"/source mkdir -p "$TEMPDIR"/source
[ -d "$TEMPDIR"/output ] && rm -rf "$TEMPDIR"/output
mkdir -p "$TEMPDIR"/output mkdir -p "$TEMPDIR"/output
tar -xf "$PACKAGE" -C "$TEMPDIR" source.sh tar -xf "$PACKAGE" -C "$TEMPDIR" source.sh
if tar -xf "$PACKAGE" -C "$TEMPDIR" source-files &> /dev/null; then if tar -xf "$PACKAGE" -C "$TEMPDIR" source-files &> /dev/null; then
mv "$TEMPDIR"/source-files/* "$TEMPDIR"/ mv "$TEMPDIR"/source-files/* "$TEMPDIR"/
rm -d "$TEMPDIR"/source-files rm -d "$TEMPDIR"/source-files
fi fi
PACKAGE_SCRIPTS=()
while read line; do
PACKAGE_SCRIPTS+=("$line")
done < <(tar -tf "$PACKAGE" | grep -v -E 'source.sh|pkg.info|source-files')
tar -xf "$PACKAGE" -C "$TEMPDIR" ${PACKAGE_SCRIPTS[@]} &> /dev/null
cd "$TEMPDIR" cd "$TEMPDIR"
# Declare and run Set Variables function
function SetVariables() {
export BPM_PKG_NAME="${PKGINFO[name]}" export BPM_PKG_NAME="${PKGINFO[name]}"
export BPM_PKG_DESC="${PKGINFO[description]}" export BPM_PKG_DESC="${PKGINFO[description]}"
export BPM_PKG_VERSION="${PKGINFO[version]}" export BPM_PKG_VERSION="${PKGINFO[version]}"
export BPM_PKG_REVISION="${PKGINFO[revision]}"
[ -z "$BPM_PKG_REVISION" ] && export BPM_PKG_REVISION=1
export BPM_PKG_URL="${PKGINFO[url]}" export BPM_PKG_URL="${PKGINFO[url]}"
export BPM_PKG_ARCH="${PKGINFO[architecture]}" export BPM_PKG_ARCH="${PKGINFO[architecture]}"
IFS=',' read -r -a BPM_PKG_DEPENDS <<< "${PKGINFO[depends]}" IFS=',' read -r -a BPM_PKG_DEPENDS <<< "${PKGINFO[depends]}"
@ -63,57 +137,80 @@ export BPM_PKG_MAKE_DEPENDS
export BPM_WORKDIR="$TEMPDIR" export BPM_WORKDIR="$TEMPDIR"
export BPM_SOURCE="$TEMPDIR"/source export BPM_SOURCE="$TEMPDIR"/source
export BPM_OUTPUT="$TEMPDIR"/output export BPM_OUTPUT="$TEMPDIR"/output
}
SetVariables
# Declare Run Package Function function
function RunPkgFunction() {
if [ $# -eq 0 ]; then
echo "No function name given"
exit 1
fi
func="$1"
if [[ $(type -t "$func") == function ]]; then
echo "Running ${func}() function..."
bash -e -c "$func"
if [ $? -ne 0 ]; then
echo "Failed to run ${func}() function in source.sh"
exit 1
fi
fi
}
# Read source.sh file and source functions
set -a set -a
source source.sh source source.sh
set +a set +a
if [[ $(type -t prepare) == function ]]; then cd "$BPM_WORKDIR"
echo "Running prepare() function..." RunPkgFunction prepare
bash -e -c prepare
if [ $? -ne 0 ]; then
echo "Failed to run prepare() function in source.sh"
exit 1
fi
fi
cd "$BPM_SOURCE" cd "$BPM_SOURCE"
if [[ $(type -t build) == function ]]; then RunPkgFunction build
echo "Running build() function..."
bash -e -c build
if [ $? -ne 0 ]; then
echo "Failed to run build() function in source.sh"
exit 1
fi
fi
cd "$BPM_SOURCE" cd "$BPM_SOURCE"
if [[ $(type -t check) == function ]] && [ -z "$SKIPCHECK" ]; then if [ -z "$SKIPCHECK" ]; then
echo "Running check() function..." RunPkgFunction check
check
if [ $? -ne 0 ]; then
echo "Failed to run check() function in source.sh"
exit 1
fi
fi fi
# Packaging all packages
for func in $(typeset -F | awk '{print $3}' | grep '^package'); do
cd "$BPM_SOURCE" cd "$BPM_SOURCE"
if ! [[ $(type -t package) == function ]]; then if [[ "$func" == "package" ]]; then
echo "Failed to locate package() function in source.sh" pkgname="$BPM_PKG_NAME"
exit 1 ReadPkgInfo
else
pkgname="${func##package-}"
ReadPkgInfo "$pkgname"
fi fi
echo "Running package() function..." SetVariables
touch "$TEMPDIR"/fakeroot_file echo "Running ${func}() function..."
fakeroot -s "$TEMPDIR"/fakeroot_file bash -e -c package touch "$TEMPDIR"/fakeroot_file_"$pkgname"
fakeroot -s "$TEMPDIR"/fakeroot_file_"$pkgname" bash -e -c "$func"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Failed to run package() function in source.sh" echo "Failed to run ${func}() function in source.sh"
exit 1 exit 1
fi fi
cd "$BPM_WORKDIR" cd "$BPM_WORKDIR"
touch pkg.info touch pkg.info
if [[ "$pkgname" == "$BPM_PKG_NAME" ]]; then
echo "${PKGINFO_FILE}" > pkg.info
else
echo "${PKGINFO_FILE}" > pkg.info
fi
echo "${PKGINFO_FILE}" > pkg.info echo "${PKGINFO_FILE}" > pkg.info
sed -i "s/architecture:.*/architecture: ${ARCH}/g" pkg.info sed -i "s/architecture:.*/architecture: ${ARCH}/g" pkg.info
sed -i 's/type:.*/type: binary/g' pkg.info sed -i 's/type:.*/type: binary/g' pkg.info
fakeroot -i "$TEMPDIR"/fakeroot_file -s "$TEMPDIR"/fakeroot_file tar -czpf "$BPM_PKG_NAME".tar.gz pkg.info output --transform 's/output/files/' fakeroot -i "$TEMPDIR"/fakeroot_file_"$pkgname" find "$TEMPDIR"/output -mindepth 1 -printf "%P %#m %U %G %s\n" > "$TEMPDIR"/pkg.files
mv "$BPM_PKG_NAME".tar.gz "$DIR"/"$BPM_PKG_NAME"-"$BPM_PKG_VERSION"-"$ARCH".bpm find output -printf "%P\n" | fakeroot -i "$TEMPDIR"/fakeroot_file_"$pkgname" tar -czf files.tar.gz --no-recursion -C output -T -
echo "Package conversion complete!" tar -cf "$DIR"/"$pkgname"-"$BPM_PKG_VERSION"-"$BPM_PKG_REVISION"-"$ARCH".bpm --owner=0 --group=0 -C "$TEMPDIR" pkg.info pkg.files ${PACKAGE_SCRIPTS[@]} files.tar.gz
echo "Packaged ${pkgname} successfully!"
rm "$TEMPDIR"/fakeroot_file_"$pkgname"
rm -r output/
mkdir output
rm pkg.info
done
if [ -z "$KEEP" ]; then if [ -z "$KEEP" ]; then
rm -rf "$TEMPDIR" rm -rf "$TEMPDIR"

View File

@ -1,29 +1,39 @@
#!/bin/bash #!/bin/bash
if [ $# -eq 0 ]
then if [ -f .compilation-options ]; then
echo "No output package name given!" source ./.compilation-options
exit 1
fi fi
while getopts "cska:" flag; do while getopts "cskfa:" flag; do
case "$flag" in case "$flag" in
c) CONVERT=true;; c) CONVERT=true;;
k) KEEP=true;; k) KEEP=true;;
s) SKIPCHECK=true;; s) SKIPCHECK=true;;
a) ARCHITECTURE="${OPTARG}";; f) FORCE=true;;
a) ARCH="${OPTARG}";;
*) exit 1;; *) exit 1;;
esac esac
done done
output="${@:$OPTIND:1}" if [ -f pkg.info ]; then
echo "pkg.info file found"
else
echo "pkg.info file not found in $PWD"
exit 1
fi
if [[ ! "$output" =~ ^[a-z.A-Z0-9_-]{1,}$ ]]; then output="${@:$OPTIND:1}"
if [ -z "$output" ]; then
pkgname=$(grep "^name: " pkg.info)
output=$(echo "$pkgname" | cut -d' ' -f2)"-src.bpm"
fi
if [ -z "$output" ] || [[ ! "$output" =~ ^[a-z.A-Z0-9_-]{1,}$ ]]; then
echo "Invalid output name! The name must only contain letters, numbers, hyphens or underscores!" echo "Invalid output name! The name must only contain letters, numbers, hyphens or underscores!"
exit 1 exit 1
fi fi
type="binary" type="binary"
toCompress=("pkg.info") toCompress=()
echo "Creating package with the name $output..." echo "Creating package with the name $output..."
@ -51,6 +61,10 @@ else
echo "post_install.sh file found" echo "post_install.sh file found"
toCompress+=("post_install.sh") toCompress+=("post_install.sh")
fi fi
if [ -f pre_remove.sh ]; then
echo "pre_remove.sh file found"
toCompress+=("pre_remove.sh")
fi
if [ -f post_remove.sh ]; then if [ -f post_remove.sh ]; then
echo "post_remove.sh file found" echo "post_remove.sh file found"
toCompress+=("post_remove.sh") toCompress+=("post_remove.sh")
@ -67,23 +81,19 @@ else
fi fi
fi fi
if [ -f pkg.info ]; then for pkginfo in ./pkg.inf*; do
echo "pkg.info file found" pkginfo=$(basename "$pkginfo")
else echo "${pkginfo} file found"
echo "pkg.info file not found in $PWD" toCompress+=("$pkginfo")
exit 1 done
fi
echo "Creating $type package as $output" echo "Creating $type package as $output"
tar -c --owner=0 --group=0 --no-same-owner -zf "$output" "${toCompress[@]}" tar -c --owner=0 --group=0 --no-same-owner -f "$output" "${toCompress[@]}"
if [ ! -z "$CONVERT" ] && "$CONVERT" && [[ "$type" == "source" ]]; then if [ ! -z "$CONVERT" ] && "$CONVERT" && [[ "$type" == "source" ]]; then
args=() args=()
if ! [ -z "$KEEP" ]; then [ -n "$KEEP" ] && args+=("-k")
args+=("-a" "$ARCHITECTURE") [ -n "$SKIPCHECK" ] && args+=("-s")
fi [ -n "$FORCE" ] && args+=("-f")
if ! [ -z "$SKIPCHECK" ]; then bpm-convert "${args[@]}" -a "$ARCH" "$output"
args+=("-s")
fi
bpm-convert "${args[@]}" -a "$ARCHITECTURE" "$output"
fi fi

View File

@ -19,7 +19,6 @@ if [ $# -eq 0 ]; then
exit exit
fi fi
NAME="package-name"
DESCRIPTION="Default package description" DESCRIPTION="Default package description"
VERSION="1.0" VERSION="1.0"
#URL="https://my.project.url/ (Optional)" #URL="https://my.project.url/ (Optional)"
@ -79,6 +78,10 @@ if [ -z "${DIRECTORY}" ]; then
exit 1 exit 1
fi fi
if [ -z "${NAME}" ]; then
NAME="${DIRECTORY}"
fi
if [[ ! "${DIRECTORY}" == "/"* ]]; then if [[ ! "${DIRECTORY}" == "/"* ]]; then
DIRECTORY="${PWD}/${DIRECTORY}" DIRECTORY="${PWD}/${DIRECTORY}"
fi fi

80
create-repository-data Executable file
View File

@ -0,0 +1,80 @@
#!/bin/bash
containsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
SCRIPT_PATH=$(realpath "$0")
SCRIPT_DIR=$(dirname "$SCRIPT_PATH")
DEEP=false
PKGS=()
while getopts "d" flag; do
case "$flag" in
d) DEEP=true
shopt -s globstar;;
*) >&2 echo "Unknown flag ${flag}"
exit 2;;
esac
done
if [ -z "${@:$OPTIND:1}" ]; then
echo "You have not specified a repository"
exit 1
fi
if ! [ -d "${@:$OPTIND:1}" ]; then
>&2 echo "The given path is not a directory"
exit 1
fi
if realpath "${@:$OPTIND:1}" &> /dev/null; then
REPO=$(realpath "${@:$OPTIND:1}")
fi
shopt -s nullglob
create_entry() {
if [ $# -eq 0 ]; then
return 0
fi
if ! [ -f "$1" ]; then
return 0
fi
info="info:"$'\n'
info+=$(tar -xf "$pkg" pkg.info -O | sed 's/^/ /g')
package=$(echo "$info" | grep 'name: ' | xargs | awk '{print $2}')
if ! echo "$info" | grep -q '^ type: binary'; then
>&2 echo "The following package is not a binary package: ${package}"
exit 1
fi
if containsElement "$package" "${PKGS[@]}"; then
>&2 echo "The following package was found in more than 1 package archives: ${package}"
exit 1
fi
PKGS+=("$package")
file="$(realpath -s --relative-to="$REPO" "$pkg")"
info+=$'\n'"download: ${file}"
info+=$'\n'"download_size: "$(cat "$pkg" | wc -c)
info+=$'\n'"installed_size: "$(tar -xf "$pkg" files.tar.gz -O | zcat | wc -c)
info+=$'\n---'
echo "$info"
}
if ! $DEEP; then
for arch in "$REPO"/*/; do
for pkg in "$arch"/*.bpm; do
create_entry "$pkg"
done
done
else
for arch in "$REPO"/*/; do
for pkg in "$arch"/**/*.bpm; do
create_entry "$pkg"
done
done
fi