#!/bin/bash # This is Shotcut AppImage → Porteus module build script # Version 2026-08-06 # Copyright 2023-2030, Blaze, Dankov, Russia # All rights reserved. # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # root check if [ "$(whoami)" != "root" ]; then echo -e "\nYou need to be root to run this script.\n" exit 1 fi PRGNAM=${PRGNAM:-shotcut} BUILD=${BUILD:-1} ARCH=$(uname -m) BOLD=${BOLD:-"\e[1m"} CYAN=${CYAN:-"\e[96m"} GREEN=${GREEN:-"\e[92m"} RED=${RED:-"\e[31m"} RESET=${RESET:-"\e[0m"} CWD=$(pwd) TMPDIR=/tmp/portch PKG=$TMPDIR/package-$PRGNAM PKGINFO=$PKG/var/lib/pkgtools/packages OUTPUT=${OUTPUT:-/tmp} cleanup(){ [ -d "$TMPDIR" ] && rm -rf "$TMPDIR" [ -d "$PKG" ] && rm -rf "$PKG" exit } # ---------- obtain latest version and download URL ---------- API="https://api.github.com/repos/mltframework/shotcut/releases/latest" echo -e "\nFetching latest release info..." JSON=$(wget -q -O- --header="Accept: application/vnd.github.v3+json" "$API" 2>&1) if [ $? -ne 0 ] || [ -z "$JSON" ]; then echo -e "${RED}Failed to fetch release info. Check network or install 'wget'.${RESET}" exit 1 fi VERSION=$(echo "$JSON" | grep -oP '"tag_name":\s*"\K[^"]+') if [ -z "$VERSION" ]; then echo -e "${RED}Version tag not found in JSON.${RESET}" exit 1 fi VERSION="${VERSION#v}" DOWNLOAD_URL=$(echo "$JSON" | grep -oP '"browser_download_url":\s*"\K[^"]*AppImage' | head -1) if [ -z "$DOWNLOAD_URL" ]; then echo -e "${RED}AppImage URL not found.${RESET}" exit 1 fi # ---------- check existing installation ---------- INSTALLED_VERSION="" if [ -f /opt/shotcut/version.txt ]; then INSTALLED_VERSION=$(cat /opt/shotcut/version.txt) fi if [ "$INSTALLED_VERSION" = "$VERSION" ]; then echo -e "You have the latest ${GREEN}$INSTALLED_VERSION${RESET} version of $PRGNAM" sleep 5 exit else read -p "$(echo -e Would you like to build $PRGNAM ${GREEN}$VERSION${RESET} xzm module? [y/n])" -n 1 -r -s && echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit fi fi # ---------- prepare build environment ---------- rm -rf "$PKG" "$TMPDIR" mkdir -p "$TMPDIR" "$PKG/opt/$PRGNAM" "$PKG/usr/bin" "$PKG/usr/share/applications" "$PKG/usr/share/pixmaps" # ---------- download AppImage ---------- echo -e "\nDownloading ${CYAN}${BOLD}${PRGNAM}-${VERSION}.AppImage${RESET}" wget -q --show-progress -O "$TMPDIR/shotcut-${VERSION}.AppImage" "$DOWNLOAD_URL" # ---------- extract AppImage ---------- cd "$TMPDIR" chmod +x shotcut-${VERSION}.AppImage echo -e "\nExtracting AppImage (this may take a moment)..." ./shotcut-${VERSION}.AppImage --appimage-extract 2>&1 if [ $? -ne 0 ] || [ ! -d "squashfs-root" ]; then echo -e "${RED}Extraction failed!${RESET}" cleanup fi # ====================== language selection ====================== TRANSLATIONS_DIR=$(find squashfs-root -type d -name translations -path "*/shotcut/*" 2>/dev/null | head -1) if [ -z "$TRANSLATIONS_DIR" ]; then echo -e "${RED}Translations directory not found, skipping language cleanup.${RESET}" LANG_CHOICE="en" else mapfile -t LANGUAGES < <(ls "$TRANSLATIONS_DIR"/shotcut_*.qm 2>/dev/null | \ sed -n 's/.*shotcut_\([a-z]\{2,3\}\(_[A-Z]\{2\}\)\?\)\.qm/\1/p' | sort -u) if [ ${#LANGUAGES[@]} -eq 0 ]; then echo -e "${RED}No shotcut_*.qm files found, keeping all languages.${RESET}" LANG_CHOICE="en" else echo -e "\nAvailable languages for Shotcut:" PS3="Select language to keep (type number): " select LANG_CHOICE in "${LANGUAGES[@]}"; do if [ -n "$LANG_CHOICE" ]; then echo -e "Keeping all English variants and '$LANG_CHOICE'." break else echo -e "${RED}Invalid choice. Try again.${RESET}" fi done fi fi # ---------- cleanup: docs/licenses only ---------- find squashfs-root -type d \( -name licenses -o -name doc -o -name man -o -name info \) -exec rm -rf {} + 2>/dev/null # ---------- locale/translation pruning ---------- for LOCALE_DIR in $(find squashfs-root -type d -path "*/share/locale"); do for DIR in "$LOCALE_DIR"/*; do BASENAME=$(basename "$DIR") if [[ "$BASENAME" == en* ]] || [[ "$BASENAME" == "$LANG_CHOICE"* ]]; then continue fi rm -rf "$DIR" done done for TRANS_DIR in $(find squashfs-root -type d -name translations -path "*/shotcut/*"); do for QMFILE in "$TRANS_DIR"/*.qm; do FILENAME=$(basename "$QMFILE" .qm) if [[ "$FILENAME" =~ _en ]] || [[ "$FILENAME" =~ _${LANG_CHOICE}\. ]] || [[ "$FILENAME" =~ _${LANG_CHOICE}$ ]]; then continue fi rm -f "$QMFILE" done done find squashfs-root -type d -empty -delete 2>/dev/null # ---------- install extracted contents ---------- rm shotcut-${VERSION}.AppImage mv squashfs-root/* "$PKG/opt/$PRGNAM/" 2>/dev/null mv squashfs-root/.DirIcon "$PKG/opt/$PRGNAM/" 2>/dev/null mv squashfs-root/org.shotcut.Shotcut.desktop "$PKG/opt/$PRGNAM/" 2>/dev/null rmdir squashfs-root echo "$VERSION" > "$PKG/opt/$PRGNAM/version.txt" # ---------- icon handling ---------- ICON_SRC="" for candidate in \ "$PKG/opt/$PRGNAM/.DirIcon" \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/256x256/apps/shotcut.png" \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/128x128/apps/shotcut.png" \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/64x64/apps/shotcut.png" \ "$PKG/opt/$PRGNAM/usr/share/icons/hicolor/48x48/apps/shotcut.png"; do if [ -f "$candidate" ]; then ICON_SRC="$candidate" break fi done if [ -n "$ICON_SRC" ]; then cp "$ICON_SRC" "$PKG/usr/share/pixmaps/shotcut.png" chmod 644 "$PKG/usr/share/pixmaps/shotcut.png" else echo -e "${RED}Warning: Icon not found in extracted image. Module may lack an icon.${RESET}" fi # ---------- keep original desktop file for D‑Bus registration ---------- if [ -f "$PKG/opt/$PRGNAM/org.shotcut.Shotcut.desktop" ]; then cp "$PKG/opt/$PRGNAM/org.shotcut.Shotcut.desktop" "$PKG/usr/share/applications/" chmod 644 "$PKG/usr/share/applications/org.shotcut.Shotcut.desktop" fi # wrapper script cat > "$PKG/usr/bin/shotcut" << EOF #!/bin/bash cd /opt/$PRGNAM exec ./AppRun "\$@" EOF chmod 755 "$PKG/usr/bin/shotcut" # ---------- desktop entry ---------- cat > "$PKG/usr/share/applications/$PRGNAM.desktop" << EOM [Desktop Entry] Name=Shotcut GenericName=Video Editor GenericName[ru]=Видеоредактор GenericName[es]=Editor de video GenericName[de]=Video-Editor GenericName[fr]=Éditeur vidéo GenericName[it]=Editor video GenericName[pt]=Editor de vídeo GenericName[zh_CN]=视频编辑器 Comment=Shotcut video editor Comment[ru]=Видеоредактор Shotcut Comment[es]=Editor de video Shotcut Comment[de]=Shotcut Video-Editor Comment[fr]=Éditeur vidéo Shotcut Comment[it]=Editor video Shotcut Comment[pt]=Editor de vídeo Shotcut Comment[zh_CN]=Shotcut 视频编辑器 Icon=/usr/share/pixmaps/shotcut.png Exec=shotcut %F Terminal=false Type=Application Categories=AudioVideo;Video;Editing; MimeType=application/xml; EOM # ---------- fake Slackware package info ---------- mkdir -p "$PKGINFO" cat > "$PKGINFO/$PRGNAM-$VERSION-$ARCH" << EOM PACKAGE NAME: $PRGNAM-$VERSION-$ARCH PACKAGE DESCRIPTION: shotcut: shotcut (video editor) shotcut: shotcut: Shotcut is a free, open source, cross-platform video editor. shotcut: shotcut: https://shotcut.org/ shotcut: FILE LIST: EOM cd "$PKG" || exit find . -path ./var -prune -o -print | grep -v "^\./var" >> "$PKGINFO/$PRGNAM-$VERSION-$ARCH" # ---------- create xzm module ---------- dir2xzm "$PKG" "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD.xzm" # ---------- finish ---------- if [ -f "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD.xzm" ]; then echo -e "\n${BOLD}Your $PRGNAM module is at: ${GREEN}$OUTPUT/$PRGNAM-$VERSION-${ARCH}-${BUILD}.xzm${RESET}\n${BOLD}Please copy it to your modules folder to survive a reboot.${RESET}\n" else echo -e "\n${RED}${BOLD}Failed. Your $PRGNAM module was not built.${RESET}\n" fi cleanup