Compare commits

..

18 Commits

Author SHA1 Message Date
5076c48001 Update LICENSE 2025-04-07 21:10:56 +03:00
7df29661c3 Moved over to new BPM file format 2024-10-26 18:04:04 +03:00
66c8dd5f91 Directory name will now be used as the package name if not set in bpm-setup and updated README.md 2024-10-08 10:32:58 +03:00
9372acba3f pre_update.sh package scripts will now be included in bpm files 2024-10-08 10:08:48 +03:00
efb904fa37 bpm-convert will now make sure dependencies are met if bpm is installed 2024-10-08 09:45:49 +03:00
430a233879 It is no longer necessary to type the output name of the source bpm file 2024-10-08 09:42:49 +03:00
9ef4699c0d Added make dependency detection for bpm-convert 2024-09-18 11:39:22 +00:00
c2de62c343 Fixed 'deep' repository data creation not using the updated database format 2024-09-14 14:24:37 +00:00
e4a9622ff2 Fixed package scripts not being included in bpm file 2024-09-14 14:23:36 +00:00
39b56204ae Fixed 'skip check' flag and added .compilation-options files that can alter the metadata of the output binary bpm file 2024-09-09 09:23:46 +00:00
CapCreeperGR
190a670cff Added split-package functionality and the create-repository-data script for unpac repository creation 2024-07-12 15:35:55 +00:00
CapCreeperGR
d077b13a3f Added -g flag to bpm-setup for automatic git repository initialization 2024-07-05 11:52:22 +03:00
5d868579af Multiple improvements to the BPM-Utils 2024-07-01 13:45:50 +03:00
6b82675582 bpm-convert will now read global variables in source.sh 2024-06-01 20:24:57 +03:00
8b39b3d575 Fixed minor mistake in source.default 2024-06-01 20:10:56 +03:00
3ea431b98d Added '-a <architecture>' flag to to bpm-package 2024-05-30 15:55:47 +03:00
a3a97efd59 Updated source.default, updated bpm-package and added bpm-convert
source.default now uses the new PKGBUILD-like structure
bpm-package now accepts a '-c' flag that creates an additional binary package from a source package
bpm-convert creates a binary package from a source package
2024-05-30 14:23:14 +03:00
ede04e3aba Updated README.md 2024-05-02 18:50:53 +03:00
7 changed files with 409 additions and 49 deletions

View File

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

View File

@ -8,19 +8,20 @@ BPM Utils is a package providing a number of different helper scripts for settin
## Provided Scripts
- 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
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 Linux distributions:
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
## Package Creation using BPM Utils
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)
```
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
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
@ -28,12 +29,14 @@ bpm-setup -D my_bpm_package -t <binary/source>
name: my_package
description: My package's description
version: 1.0
revision: 2 (Optional)
architecture: x86_64
url: https://www.my-website.com/ (Optional)
license: MyLicense (Optional)
type: <binary/source>
depends: dependency1,dependency2 (Optional)
make_depends: make_depend1,make_depend2 (Optional)
depends: ["dependency1","dependency2"] (Optional)
optional_depends: ["optional_depend1","optional_depend2"]
make_depends: ["make_depend1","make_depend2"] (Optional)
```
### 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)
@ -46,7 +49,7 @@ bpm-package <filename.bpm>
3) If you would like to bundle patches or other files with your source package place them in the 'source-files' directory. They will be extracted to the same location as the source.sh file during compilation
4) You need to edit your 'source.sh' file, the default source.sh template should explain the basic process of compiling your program
5) Your goal is to download your program's source code with either git, wget, curl, etc. and put the binaries under a folder called 'output' in the root of the temp directory. There is a simple example script with helpful comments in the htop-src test package
6) When you are done making your source.sh script run the following to create a package archive
6) When you are done making your source.sh script run the following to create a package archive. You may also append the -c flag to compile the package and create a binary package as well
```
bpm-package <filename.bpm>
```

217
bpm-convert Executable file
View File

@ -0,0 +1,217 @@
#!/bin/bash
if [ -f .compilation-options ]; then
source ./.compilation-options
fi
echo "$ARCH"
while getopts "ksfa:" o; do
case "${o}" in
a) ARCH="$OPTARG";;
k) KEEP=true;;
s) SKIPCHECK=true;;
f) FORCE=true;;
*) exit 1;;
esac
done
PACKAGE="${@:$OPTIND:1}"
DIR="$PWD"
if [ -z "$ARCH" ]; then
ARCH=$(uname -m)
fi
if ! [ -f "$PACKAGE" ]; then
echo "$PACKAGE is not a path to a file"
exit 1
fi
if ! file "$PACKAGE" | grep -q 'POSIX tar archive'; then
echo "$PACKAGE is not a BPM package"
exit 1
fi
if ! tar -tf "$PACKAGE" | grep -q 'source.sh'; then
echo "$PACKAGE is not a BPM source package"
exit 1
fi
echo "$Converting $PACKAGE..."
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
PKGINFO[$(echo -n "$line" | cut -d":" -f1 | xargs)]=$(echo -n "$line" | cut -d":" -f2 | xargs)
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]}"
if [ -d "$TEMPDIR" ] && [ -z "$KEEP" ]; then
rm -rf "$TEMPDIR"
fi
mkdir -p "$TEMPDIR"
mkdir -p "$TEMPDIR"/source
[ -d "$TEMPDIR"/output ] && rm -rf "$TEMPDIR"/output
mkdir -p "$TEMPDIR"/output
tar -xf "$PACKAGE" -C "$TEMPDIR" source.sh
if tar -xf "$PACKAGE" -C "$TEMPDIR" source-files &> /dev/null; then
mv "$TEMPDIR"/source-files/* "$TEMPDIR"/
rm -d "$TEMPDIR"/source-files
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"
# Declare and run Set Variables function
function SetVariables() {
export BPM_PKG_NAME="${PKGINFO[name]}"
export BPM_PKG_DESC="${PKGINFO[description]}"
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_ARCH="${PKGINFO[architecture]}"
IFS=',' read -r -a BPM_PKG_DEPENDS <<< "${PKGINFO[depends]}"
IFS=',' read -r -a BPM_PKG_MAKE_DEPENDS <<< "${PKGINFO[make_depends]}"
export BPM_PKG_DEPENDS
export BPM_PKG_MAKE_DEPENDS
export BPM_WORKDIR="$TEMPDIR"
export BPM_SOURCE="$TEMPDIR"/source
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
source source.sh
set +a
cd "$BPM_WORKDIR"
RunPkgFunction prepare
cd "$BPM_SOURCE"
RunPkgFunction build
cd "$BPM_SOURCE"
if [ -z "$SKIPCHECK" ]; then
RunPkgFunction check
fi
# Packaging all packages
for func in $(typeset -F | awk '{print $3}' | grep '^package'); do
cd "$BPM_SOURCE"
if [[ "$func" == "package" ]]; then
pkgname="$BPM_PKG_NAME"
ReadPkgInfo
else
pkgname="${func##package-}"
ReadPkgInfo "$pkgname"
fi
SetVariables
echo "Running ${func}() function..."
touch "$TEMPDIR"/fakeroot_file_"$pkgname"
fakeroot -s "$TEMPDIR"/fakeroot_file_"$pkgname" bash -e -c "$func"
if [ $? -ne 0 ]; then
echo "Failed to run ${func}() function in source.sh"
exit 1
fi
cd "$BPM_WORKDIR"
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
sed -i "s/architecture:.*/architecture: ${ARCH}/g" pkg.info
sed -i 's/type:.*/type: binary/g' pkg.info
fakeroot -i "$TEMPDIR"/fakeroot_file_"$pkgname" find "$TEMPDIR"/output -mindepth 1 -printf "%P %#m %U %G %s\n" > "$TEMPDIR"/pkg.files
find output -printf "%P\n" | fakeroot -i "$TEMPDIR"/fakeroot_file_"$pkgname" tar -czf files.tar.gz --no-recursion -C output -T -
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
rm -rf "$TEMPDIR"
fi

View File

@ -1,19 +1,39 @@
#!/bin/bash
if [ $# -eq 0 ]
then
echo "No output package name given!"
if [ -f .compilation-options ]; then
source ./.compilation-options
fi
while getopts "cskfa:" flag; do
case "$flag" in
c) CONVERT=true;;
k) KEEP=true;;
s) SKIPCHECK=true;;
f) FORCE=true;;
a) ARCH="${OPTARG}";;
*) exit 1;;
esac
done
if [ -f pkg.info ]; then
echo "pkg.info file found"
else
echo "pkg.info file not found in $PWD"
exit 1
fi
output=$1
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!"
exit 1
fi
type="binary"
toCompress=("pkg.info")
toCompress=()
echo "Creating package with the name $output..."
@ -41,10 +61,14 @@ else
echo "post_install.sh file found"
toCompress+=("post_install.sh")
fi
if [ -f pre_remove.sh ]; then
echo "pre_remove.sh file found"
toCompress+=("pre_remove.sh")
fi
if [ -f post_remove.sh ]; then
echo "post_remove.sh file found"
toCompress+=("post_remove.sh")
fi
echo "post_remove.sh file found"
toCompress+=("post_remove.sh")
fi
if [ -d source-files ]; then
if [ ! -z "$(ls -A source-files)" ]; then
echo "source-files/ directory found"
@ -57,13 +81,19 @@ else
fi
fi
if [ -f pkg.info ]; then
echo "pkg.info file found"
else
echo "pkg.info file not found in $PWD"
exit 1
fi
for pkginfo in ./pkg.inf*; do
pkginfo=$(basename "$pkginfo")
echo "${pkginfo} file found"
toCompress+=("$pkginfo")
done
echo "Creating $type package as $output"
tar -c --owner=0 --group=0 --no-same-owner -f "$output" "${toCompress[@]}"
tar -czf "$output" "${toCompress[@]}"
if [ ! -z "$CONVERT" ] && "$CONVERT" && [[ "$type" == "source" ]]; then
args=()
[ -n "$KEEP" ] && args+=("-k")
[ -n "$SKIPCHECK" ] && args+=("-s")
[ -n "$FORCE" ] && args+=("-f")
bpm-convert "${args[@]}" -a "$ARCH" "$output"
fi

View File

@ -11,6 +11,7 @@ usage () {
echo "bpm-setup -l <licenses> | Set the package licenses (Optional)"
echo "bpm-setup -t <binary/source> | Set the package type to binary or source (Defaults to binary)"
echo "bpm-setup -s <source template file> | Use a default template file (Defaults to /etc/bpm-utils/source.default)"
echo "bpm-setup -g <true/false> | Create git repository (Defaults to true)"
}
if [ $# -eq 0 ]; then
@ -18,15 +19,15 @@ if [ $# -eq 0 ]; then
exit
fi
NAME="package-name"
DESCRIPTION="Default package description"
VERSION="1.0"
#URL="https://my.project.url/ (Optional)"
#LICENSE="Your project's license (Optional)"
TYPE="binary"
SOURCE_FILE="/etc/bpm-utils/source.default"
GIT=true
while getopts "D:n:d:v:u:l:t:s:y" o; do
while getopts "D:n:d:v:u:l:t:s:g:y" o; do
case "${o}" in
D)
DIRECTORY="${OPTARG}"
@ -55,6 +56,16 @@ while getopts "D:n:d:v:u:l:t:s:y" o; do
s)
SOURCE_FILE="$(realpath ${OPTARG})"
;;
g)
if [[ "${OPTARG}" == true ]]; then
GIT=TRUE
elif [[ "${OPTARG}" == false ]]; then
GIT=false
else
echo "${OPTARG} is not a true or false value!"
exit 1
fi
;;
*)
usage
exit 1
@ -67,6 +78,10 @@ if [ -z "${DIRECTORY}" ]; then
exit 1
fi
if [ -z "${NAME}" ]; then
NAME="${DIRECTORY}"
fi
if [[ ! "${DIRECTORY}" == "/"* ]]; then
DIRECTORY="${PWD}/${DIRECTORY}"
fi
@ -99,6 +114,9 @@ if [ -z "${CONFIRM}" ]; then
fi
echo "Package type: $TYPE"
if [[ "$TYPE" == "source" ]]; then
echo "Create Git repository: $GIT"
fi
read -p "Create package directory? [y/N]: " CREATE
case $CREATE in
[Yy]* )
@ -146,6 +164,10 @@ else
echo "Source file at ${SOURCE_FILE} does not exist! Creating empty source.sh instead..."
touch source.sh
fi
if $GIT ; then
git init
echo -e "*.bpm\n.gitignore" > .gitignore
fi
echo "Package directory created successfully!"
echo "Make sure to edit the pkg.info file with the appropriate information for your package"
echo "Add your compilation code in the source.sh file. Follow the instructions on the template file on how to properly create your compilation script"

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

View File

@ -1,24 +1,32 @@
# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package
# BPM expects there to be an 'output' directory under the root of the temporary directory after this script finishes executing, otherwise your program may not be correctly installed
# It is recommended you create the 'output' directory along with a 'source' directory in the root of the temporary directory like this
echo "Compiling ${NAME}..."
# Creating SOURCE and OUTPUT variables
SOURCE="$(pwd)"/source
OUTPUT="$(pwd)"/output
# Creating the 'source' and 'output' directories
mkdir "$SOURCE"
mkdir "$OUTPUT"
# Creating DOWNLOAD and FILENAME variables
DOWNLOAD="https://www.my-url.com/file.tar.gz"
# BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE
# BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT
DOWNLOAD="https://wwww.my-url.com/file.tar.gz"
FILENAME="${DOWNLOAD##*/}"
# Downloading files
wget "$DOWNLOAD"
# Extracting archive into 'source'
tar -xvf "$FILENAME" --strip-components=1 -C "$SOURCE"
# Changing directory into 'source'
cd "$SOURCE"
# Configuring and compiling ${NAME}
./configure --prefix=/usr
make
make install DESTDIR="$OUTPUT"
echo "${NAME} compilation complete!"
# The prepare function is executed in the root of the temp directory
# This function is used for downloading files and putting them into the correct location
prepare() {
wget "$DOWNLOAD"
tar -xvf "$FILENAME" --strip-components=1 -C "$BPM_SOURCE"
}
# The build function is executed in the source directory
# This function is used to compile the source code
build() {
./configure --prefix=/usr
make
}
# The check function is executed in the source directory
# This function is used to run tests to verify the package has been compiled correctly
check() {
make check
}
# The package function is executed in the source directory
# This function is used to move the compiled files into the output directory
package() {
make DESTDIR="$BPM_OUTPUT" install
}