Skip to content

Instantly share code, notes, and snippets.

@Guiorgy
Last active April 23, 2024 13:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Guiorgy/c3a38ddb9b6f0e6284891388065b971f to your computer and use it in GitHub Desktop.
Save Guiorgy/c3a38ddb9b6f0e6284891388065b971f to your computer and use it in GitHub Desktop.
Download the latest, or a specified, Fastfetch release source and build a DEB package
#!/usr/bin/env bash
# usage examples:
# $ ./build.sh
# $ ./build.sh 2.7.0
set -Eeo pipefail # exit on error
handle_error() {
error_code=$?
echo -e "${RED}Script failed on line #${1} with error code ${error_code}!${NOCOLOR}" 1>&2
cleanup
exit $error_code
}
trap 'handle_error $LINENO' ERR
# colors for colored output
NOCOLOR='\033[0m'
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[0;37m'
error() {
echo -e "${RED}Error${NOCOLOR}: ${1}" 1>&2
cleanup
if [[ -n "$2" ]]; then
exit "$2"
else
exit 1
fi
}
information() {
COLOR="$YELLOW"
if [ $# -gt 1 ]; then
case "$1" in
--*)
case "$1" in
--no-color) COLOR="$NOCOLOR" ;;
--red) COLOR="$RED" ;;
--green) COLOR="$GREEN" ;;
--yellow) COLOR="$YELLOW" ;;
--blue) COLOR="$BLUE" ;;
--purple) COLOR="$PURPLE" ;;
--cyan) COLOR="$CYAN" ;;
--white) COLOR="$WHITE" ;;
*) error 'Unrecognized color' ;;
esac
shift
;;
*) ;;
esac
fi
if [[ $# -gt 1 ]]; then
if [[ -n "$1" ]]; then
echo -e -n "${COLOR}${1}${NOCOLOR}: "
fi
shift
else
echo -e -n "${COLOR}Information${NOCOLOR}: "
fi
echo -e "$1"
}
cleanupAttempted=0
cleanup() {
if [[ $cleanupAttempted -eq 1 ]]; then
return
fi
cleanupAttempted=1
# return to the initial working directory
cd "$workingDirectory"
if [[ -f "${releaseTag}.tar.gz" ]]; then
information 'Cleanup' "Removing the downloaded source archive '${BLUE}${releaseTag}.tar.gz${NOCOLOR}'"
rm "${releaseTag}.tar.gz"
fi
if [[ -d "fastfetch-${releaseTag}" ]]; then
information 'Cleanup' "Removing the extracted source directory '${BLUE}fastfetch-${releaseTag}${NOCOLOR}'"
rm -rf "fastfetch-${releaseTag}"
fi
}
# remember the current working directory for cleanup
workingDirectory=$(pwd)
# check if cmake is available
if ! command -v cmake &>/dev/null; then
error "CMake is not installed. Run '${BLUE}sudo apt install cmake${NOCOLOR}' to install"
fi
# check if a specific release tag was passed as the first argument
releaseTag="$1"
if [[ -z "$releaseTag" ]]; then
information '' 'Getting the latest release tag from github'
response=$(curl -s 'https://api.github.com/repos/fastfetch-cli/fastfetch/releases/latest')
releaseTag=$(echo "$response" | grep -m 1 '"tag_name"' | cut -d : -d '"' -f 4) \
|| error "Failed to grep the release tag. Response: ${BLUE}${response}${NOCOLOR}"
information '' "Latest release tag: ${BLUE}${releaseTag}${NOCOLOR}"
fi
# validate that the release tag is in the format "x.y.z"
if ! [[ "$releaseTag" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
error "The specified release tag '${BLUE}${releaseTag}${NOCOLOR}' is not in the correct format"
fi
# get the list of already built tags
builtTags=$(find . -mindepth 1 -maxdepth 1 -type f -name '*.deb')
if [[ -n "$builtTags" ]]; then
builtTags=$( \
echo "$builtTags" \
| grep -o 'fastfetch-[0-9]\+\.[0-9]\+\.[0-9]\+-Linux.deb' \
| cut -d - -f 2 \
)
# check if the specified release tag is already built
if [[ "$builtTags" =~ "$releaseTag" ]]; then
information --yellow "Already Built" "Release tag '${BLUE}${releaseTag}${NOCOLOR}' already built"
exit 0
fi
fi
# download source archive
wget "https://github.com/fastfetch-cli/fastfetch/archive/refs/tags/${releaseTag}.tar.gz" || error "Failed to download release '${BLUE}${releaseTag}${NOCOLOR}'"
# extract the tar.gz archive
# - x: extract
# - v: verbose output
# - z: use gzip
# - f: archive file path
tar -xvzf "${releaseTag}.tar.gz" || error 'Failed to unpack the source archive'
# cd into the extracted directory
cd "fastfetch-${releaseTag}"
# modify the package target of CMakeLists.txt to only build a DEB package
sed -i \
-e 's/set(CPACK_GENERATOR "TGZ;ZIP")/set(CPACK_GENERATOR "DEB")/g' \
-e 's/set(CPACK_GENERATOR "${CPACK_GENERATOR};.*")/set(CPACK_GENERATOR "DEB")/g' \
CMakeLists.txt \
|| error 'Failed to modify CMakeList.txt'
# create a build directory and cd into it
mkdir -p build
cd build
# build the package
cmake .. || error 'Failed to generate a CMake project build system'
cmake --build . --target package || 'Failed to build using CMake'
# find the built package for the current platform
package=$(find . -maxdepth 1 -type f -name 'fastfetch-*.deb') \
|| error "Failed to find the built package in -e$(ls | sed -e $'s/^/\t/')"
# move the built package to the initial working directory
mv "$package" ../../"fastfetch-${releaseTag}-Linux.deb" \
|| error "Failed to move the built package '$package' from:\n$(ls | sed -e $'s/^/\t/')\nto:\n$(ls | sed -e $'s/^/\t/')"
# remove downloaded source files and build artifacts
cleanup
# print the done message and instructions to install
information --green 'Done' "Successfully built ${BLUE}fastfetch-${releaseTag}-Linux.deb${NOCOLOR}"
information '' "Run '${BLUE}sudo apt install ./fastfetch-${releaseTag}-Linux.deb${NOCOLOR}' to install"
@Guiorgy
Copy link
Author

Guiorgy commented Mar 12, 2024

The script dumps the built packages in the working directory and expects the user to manually install the package.

You may modify the script to automatically run apt install ./fastfetch-[TAG]-Linux.deb, but instead you may prefer to crate a local package repository and add it to the apt sources:

  • Install dpkg-dev if you don't have it
    sudo apt-get install dpkg-dev
  • Add a line to the bottom of the shell script
    dpkg-scanpackages --multiversion . /dev/null | gzip -9c > Packages.gz
  • Create a source list file inside /etc/apt/sources.list.d/
    nano /etc/apt/sources.list.d/fastfetch-local.list
  • Add a reference to the directory where fastfetch packages are built
    deb [trusted=yes] file:/[PATH_TO_THE_DIRECTORY_WITH_THE_BUILD_SCRIPT] ./
  • Optionally, to remove dpkg-scanpackages warnings on missing override file
    • Create an override file in the directory with the build script, for example
      echo 'fastfetch optional utils' > overrides
    • Modify the shell script to use the created overrides file instead of /dev/null
      dpkg-scanpackages --multiversion . overrides | gzip -9c > Packages.gz

After doing the above and updating apt (apt update) you may simply install/upgrade fastfetch as if it were a normal package

  • apt list -a fastfetch
  • apt install fastfetch
  • apt install --only-upgrade fastfetch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment