Skip to content

Instantly share code, notes, and snippets.

@ruario
Last active July 22, 2022 18:42
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ruario/4ef8ca34fb4d6c8eccc0e9b10c86d672 to your computer and use it in GitHub Desktop.
Save ruario/4ef8ca34fb4d6c8eccc0e9b10c86d672 to your computer and use it in GitHub Desktop.
This script will convert an official Vivaldi Linux package into Slackware package format (it should work on any Linux distro, under macOS or even using BusyBox tools)
#!/bin/sh -eu
# This script will convert an official Vivaldi Linux package into Slackware
# package format.
#
# To use, just run this script, followed by the name of the Vivaldi package.
#
# Note: Since this script was created with Slackware 15 and above in mind, it
# uses the new 'douninst.sh' script to clear down any proprietary media libs
# fetched by 'update-ffmpeg' during post install.
#
# If you run 14.2, the UNINSTALL-Slackware-14.2.txt in the doc directory
# (also mentioned below) explains any post cleanup you might wish to perform.
# Take the first command line argument as the name of the Vivaldi package or
# if nothing is provided, look in the current working directory for the most
# recent file named like a Vivaldi package
if [ -n "${1:-}" ]; then
VIVPKG="$1"
else
VIVPKG="$(ls -dt vivaldi-s* 2>/dev/null | grep -m1 '\.\(deb\|rpm\)$' 2>/dev/null ||:)"
if [ -n "${VIVPKG:-}" ]; then
echo "Found \"$VIVPKG\" as a potential source package."
else
echo "No Vivaldi package was found in the current working directory" >&2
exit 1
fi
fi
# Check that the package is correctly named
if ! echo "${VIVPKG##*/}" | grep -qxE "vivaldi-(stable|snapshot)[_-](([0-9]+\.){3}[0-9]+)-[0-9]+[_\.](aarch64|amd64|arm64|armhf|armv.hl|x86_64)\.(rpm|deb)"; then
echo "\"${VIVPKG##*/}\" is oddly named." >&2
echo "Specify the name of the package you wish to convert as the first argument to this script." >&2
exit 1
fi
# Check that the package is present and readable on the filesystem
if ! [ -r "$VIVPKG" ]; then
echo "\"${VIVPKG##*/}\" cannot be accessed." >&2
exit 1
fi
# Set some basic variables
case "$VIVPKG" in
*rpm)
PKGNAME="$(echo "${VIVPKG##*/}" | cut -d- -f1-2)"
VERSION="$(echo "${VIVPKG##*/}" | cut -d- -f3)"
ARCH="$(echo ${VIVPKG%.rpm} | cut -d. -f5)"
;;
*deb)
PKGNAME="$(echo "${VIVPKG##*/}" | cut -d_ -f1)"
VERSION="$(echo "${VIVPKG##*/}" | cut -d_ -f2 | cut -d- -f1)"
ARCH="$(echo ${VIVPKG%.deb} | cut -d_ -f3)"
;;
esac
case $ARCH in
aarch64|arm64) ARCH=arm64 ;;
amd64) ARCH=x86_64 ;;
arm*) ARCH=arm ;;
esac
BUILD=${BUILD:-1}
TAG=${TAG:-ruario}
PKGTYPE="${PKGTYPE:-tbz}"
OUTPUT="$PWD"
PACKAGE="$OUTPUT/$PKGNAME-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
REPACKDIR="$(mktemp -d -t vivaldi-repackage.XXXXXX)/pkg"
# This function can be used in place of Slackware's makepkg, with the added
# bonuses that it is able to make packages with root owned files when run as
# a regular user and it will work on macOS. It will also work under BusyBox
# (if you are root).
mkpkg() {
if find * -type l | grep -qm1 .; then
mkdir -p install
find * -type l -print0 |\
xargs -0 -I@ sh -c 'for l in "@";do printf "(*cd*${l%/*}*;*"; echo "rm*-rf*${l##*/}*)"; printf "(*cd*${l%/*}*;*"; echo "ln*-sf*"$(readlink "$l")"*${l##*/}*)"; done' |\
sed 's/ /\\ /g;s/\*/ /g' > install/symlinks
find * -type l -delete
if [ -f "install/doinst.sh" ]; then
printf '\n' | cat - install/doinst.sh >> install/symlinks
fi
mv install/symlinks install/doinst.sh
fi
case "$1" in
*tbz)
if command -v lbzip2 >/dev/null 2>&1; then
COMPRESSOR=lbzip2
else
COMPRESSOR=bzip2
fi
;;
*tgz)
if command -v pigz >/dev/null 2>&1; then
COMPRESSOR=pigz
else
COMPRESSOR=gzip
fi
;;
*txz)
if command -v xz >/dev/null 2>&1; then
COMPRESSOR='xz -T0'
# We might still be able to make this work on macOS
elif tar --version | grep -q 'libarchive.*liblzma'; then
LIBARCHIVEXZ=J
COMPRESSOR='cat -'
else
echo "No XZ compressor found" >&2
exit 1
fi
;;
*)
echo "Unknown compression type" >&2
exit 1
;;
esac
if tar --version | grep -q libarchive; then
(echo ./; find *) | tar --no-recursion -T- --uname root --gname root -c${LIBARCHIVEXZ:-}f- | $COMPRESSOR > "$1"
else
# I would like this script to work on any system but BusyBox tar does not
# allow changing permissions of the fly. However if the script is run as
# root it should work in a pure BusyBox environment as well.
if tar --version | grep -q busybox; then
if [ "$(whoami)" = 'root' ];then
chown -R root:root .
else
echo "To run this under BusyBox, you must be root" >&2
cd "$OUTPUT"
rm -r "$REPACKDIR"
exit 1
fi
else
TAR_OWNERSHIP="--owner root --group root"
fi
(echo ./; find *) | tar --no-recursion -T- ${TAR_OWNERSHIP:-} -cf- | $COMPRESSOR > "$1"
fi
echo "Slackware package \"${1##*/}\" created."
}
# Make the basic directory structure
mkdir -p "$REPACKDIR/install" "$REPACKDIR/var/lib/pkgtools/douninst.sh" "$REPACKDIR/usr/doc/$PKGNAME-$VERSION"
# Add a this script to doc directory
cat "$0" > "$REPACKDIR/usr/doc/$PKGNAME-$VERSION/${0##*/}"
# Extract the to the repacking directory.
correct_offset () {
# Some strings implementations output the offset as octal, test for this
# and convert to decimal if needed (note: '-td' is not always available)
[ "$(printf 'popular\novel' | strings -o | sed -n '/v/s/ *\([0-9][0-9]*\) .*/\1/p')" -eq 10 ] && XZ_OFFSET="$(printf '%d' "0$XZ_OFFSET")"
}
if [ "${VIVPKG##*.}" = 'rpm' ]; then
if command -v bsdtar >/dev/null 2>&1; then
bsdtar Cfx "$REPACKDIR" "$VIVPKG" ./opt ./usr
else
XZ_OFFSET="$(strings -o "$VIVPKG" | grep -Fm1 7zXZ | sed 's/ *\([0-9][0-9]*\) .*/\1/')"
correct_offset
tail -c+"$XZ_OFFSET" "$VIVPKG" | xz -d | (cd "$REPACKDIR" && cpio --quiet -id ./opt\* ./usr\*)
fi
else
if command -v bsdtar >/dev/null 2>&1; then
bsdtar xOf "$VIVPKG" data.tar.xz | bsdtar Cfx "$REPACKDIR" - ./opt ./usr
else
XZ_OFFSET="$(strings -o "$VIVPKG" | grep -Fm2 7zXZ | tail -n1 | sed 's/ *\([0-9][0-9]*\) .*/\1/')"
correct_offset
tail -c+"$XZ_OFFSET" "$VIVPKG" | xz -d 2>/dev/null | tar -C "$REPACKDIR" -xf - ./opt ./usr
fi
# These only contain Debian specific stuff
rm -rf "$REPACKDIR/usr/share/doc" "$REPACKDIR/usr/share/menu" "$REPACKDIR/opt/${PKGNAME%-stable}/cron"
fi
# Add a 'vivaldi' symlink for stable
cd "$REPACKDIR"
[ "${PKGNAME%-stable}" = 'vivaldi' ] && ln -s /opt/${PKGNAME%-stable}/${PKGNAME%-stable} usr/bin/${PKGNAME%-stable}
# Setup icons for use with the .desktop file.
for PNG in opt/${PKGNAME%-stable}/product_logo_*.png; do
PNG_SIZE="$(echo $PNG | grep -o '[0-9]\+')"
mkdir -p usr/share/icons/hicolor/${PNG_SIZE}x$PNG_SIZE/apps
ln -s /$PNG usr/share/icons/hicolor/${PNG_SIZE}x$PNG_SIZE/apps/${PKGNAME%-stable}.png
done
# Add various package meta-data
cat <<EOF>install/slack-desc
$PKGNAME: $PKGNAME (web browser)
$PKGNAME:
$PKGNAME: Experience the web in a whole new way with Vivaldi.
$PKGNAME:
$PKGNAME: Vivaldi is a browser that has the features you need, a style that fits
$PKGNAME: and values you can stand by. Your browser matters. Take control with
$PKGNAME: Vivaldi.
$PKGNAME:
$PKGNAME: Home Page: https://vivaldi.com
$PKGNAME:
$PKGNAME:
EOF
cat <<EOF>install/doinst.sh
if [ -x /usr/bin/update-desktop-database ]; then
/usr/bin/update-desktop-database -q usr/share/applications >/dev/null 2>&1
fi
# Installs a third party libffmpeg.so that supports proprietary media
if [ -x /opt/${PKGNAME%-stable}/update-ffmpeg ]; then
nohup /opt/${PKGNAME%-stable}/update-ffmpeg >/dev/null 2>&1 &
fi
EOF
cat <<EOF>var/lib/pkgtools/douninst.sh/$PKGNAME-$VERSION-$ARCH-$BUILD$TAG
# Remove any lib fetched by update-ffmpeg, when doinst.sh was first run
if ls /var/opt/${PKGNAME%-stable}/media-codecs-*/libffmpeg.so >/dev/null 2>&1; then
rm /var/opt/${PKGNAME%-stable}/media-codecs-*/libffmpeg.so
fi
if [ -d /var/opt/${PKGNAME%-stable} ]; then
# This removes directory trees that are empty or only populated by other
# empty directories.
find /var/opt/${PKGNAME%-stable} -depth -type d -empty -exec rmdir {} \;
fi
EOF
chmod +x var/lib/pkgtools/douninst.sh/$PKGNAME-$VERSION-$ARCH-$BUILD$TAG
# Add a note about uninstall on Slackware 14.2
cat <<EOF>"$REPACKDIR/usr/doc/$PKGNAME-$VERSION/UNINSTALL-Slackware-14.2.txt"
Since '${0##*/}' was created with Slackware 15 and above in mind, it uses the
new 'douninst.sh' script to clear down any proprietary media libs fetched by
'update-ffmpeg' during post install.
If you run ≤14.2, make a copy of the douninst.sh *before* uninstall:
cp /var/lib/pkgtools/douninst.sh/$PKGNAME-$VERSION-$ARCH-$BUILD$TAG .
Then simply run it as root after uninstall.
(If you forget it is not the end of the world, you will just potentially
leave behind a small file [libffmpeg.so] under /var/opt/vivaldi*)
EOF
# Make sure the file permissions are ok
chmod -R u+w,go+r-w,a-s .
# Create the Slackware package
mkpkg "$PACKAGE"
# Cleanup
cd "$OUTPUT"
rm -r "$REPACKDIR"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment