From c99c141d4a74ae483f8e099cbfde3c4abd299f85 Mon Sep 17 00:00:00 2001 From: Jun <75189933+MXS-Jun@users.noreply.github.com> Date: Fri, 31 Jan 2025 21:03:04 +0800 Subject: [PATCH] Add files via upload --- AppImage2Deb.sh | 411 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 AppImage2Deb.sh diff --git a/AppImage2Deb.sh b/AppImage2Deb.sh new file mode 100644 index 0000000..fc0eac2 --- /dev/null +++ b/AppImage2Deb.sh @@ -0,0 +1,411 @@ +#!/usr/bin/env bash + +# 禁用辅助功能支持,减少 zenity 的报错输出 +export GTK_A11Y=none + +# 读取 AppImage 文件地址 +APPIMAGE_FILE=`zenity --file-selection --title="选择 AppImage 文件"` + +case $? in + 0) + echo "[STATUS] APPIMAGE_FILE=${APPIMAGE_FILE}" + ;; + 1) + echo "[WARN] 没有选择文件" + exit 1 + ;; + -1) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 创建工作目录 +APPIMAGE_NAME=`basename "${APPIMAGE_FILE}"` +WORK_DIR=`realpath "./${APPIMAGE_NAME%.*}"` + +mkdir "${WORK_DIR}" + +case $? in + 0) + echo "[STATUS] 工作目录创建成功" + echo "[STATUS] APPIMAGE_NAME=${APPIMAGE_NAME}" + echo "[STATUS] WORK_DIR=${WORK_DIR}" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 复制 AppImage 到工作目录 +cp "${APPIMAGE_FILE}" "${WORK_DIR}" + +case $? in + 0) + echo "[STATUS] 复制 AppImage 到工作目录成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 赋予 AppImage 可执行权限 +PASSWORD=`zenity --entry \ +--title="输入密码" \ +--text="输入 sudo 密码以赋权 AppImage 文件" \ +--entry-text "" \ +--hide-text` + +case $? in + 0) + echo "[STATUS] PASSWORD=${PASSWORD}" + ;; + 1) + echo "[WARN] 取消输入密码" + exit 1 + ;; + -1) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +(echo "${PASSWORD}" | sudo -S chmod +x "${WORK_DIR}/${APPIMAGE_NAME}") + +case $? in + 0) + echo "[STATUS] AppImage 可执行权限已经成功赋予" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 进入工作目录 +cd "${WORK_DIR}" + +case $? in + 0) + echo "[STATUS] 进入工作目录成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 解压 AppImage +"./${APPIMAGE_NAME}" --appimage-extract > /dev/null + +case $? in + 0) + echo "[STATUS] AppImage 解压成功" + rm "./${APPIMAGE_NAME}" + echo "[STATUS] 复制到工作目录的 AppImage 删除成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 获取必要的 deb 打包信息 +zenity --forms --title="获取必要信息" \ + --text="输入必要的 deb 打包信息" \ + --separator=$'\n' \ + --add-entry="包名" \ + --add-entry="版本" \ + --add-entry="作者" \ + --add-entry="邮箱" > info.txt + +case $? in + 0) + echo "[STATUS] 必要的 deb 打包信息已写入到 info.txt" + ;; + 1) + echo "[WARN] 取消输入 deb 打包信息" + exit 1 + ;; + -1) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +mapfile -t INFO_LINES < "./info.txt" + +for i in "${!INFO_LINES[@]}"; do + trimmed_line=$(echo "${INFO_LINES[$i]}" | sed 's/^[ \t]*//;s/[ \t]*$//') + INFO_LINES[$i]="$trimmed_line" +done + +case $? in + 0) + echo "[STATUS] 已读取 info.txt 中存储的信息到 INFO_LINES" + echo "[STATUS] INFO_LINES="${INFO_LINES[@]}"" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +ID="${INFO_LINES[0]}" +VERSION="${INFO_LINES[1]}" +MAINTAINER="${INFO_LINES[2]}" +MAIL="${INFO_LINES[3]}" + +echo "[STATUS] ID=${ID}" +echo "[STATUS] VERSION=${VERSION}" +echo "[STATUS] MAINTAINER=${MAINTAINER}" +echo "[STATUS] MAIL=${MAIL}" + +# 构建符合 uos 的 deb 打包标准的目录结构 +{ + mkdir "./${ID}/" + mkdir "./${ID}/DEBIAN/" + touch "./${ID}/DEBIAN/control" + + mkdir -p "./${ID}/opt/apps/${ID}/entries/applications/" + mkdir -p "./${ID}/opt/apps/${ID}/entries/icons/hicolor/512x512/apps/" + mkdir -p "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalable/apps/" + + mkdir "./${ID}/opt/apps/${ID}/files/" + + touch "./${ID}/opt/apps/${ID}/info" +} + +case $? in + 0) + echo "[STATUS] 符合 uos 的 deb 打包标准的目录结构构建成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 写入 info 文件 +echo -e "{\n \"appid\": \"${ID}\"\n}" > "./${ID}/opt/apps/${ID}/info" + +case $? in + 0) + echo "[STATUS] 写入 info 文件成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 移动 AppImage 解压后的 squashfs-root/ 内容到 bin/ +mv "./squashfs-root/" "./${ID}/opt/apps/${ID}/files/" +mv "./${ID}/opt/apps/${ID}/files/squashfs-root/" "./${ID}/opt/apps/${ID}/files/bin/" + +case $? in + 0) + echo "[STATUS] 移动 AppImage 解压后的 squashfs-root/ 内容到 bin/ 成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 创建并写入内容到 start.sh 文件 +touch "./${ID}/opt/apps/${ID}/files/start.sh" + +{ + printf "#!/usr/bin/env bash\n" + printf 'if [ -n "$1" ]; then'"\n" + printf ' file_path="$1"'"\n" + printf ' file_path="${file_path#file://}"'"\n" + printf " /opt/apps/${ID}/files/bin/AppRun "'"${file_path}"'"\n" + printf "else\n" + printf " /opt/apps/${ID}/files/bin/AppRun\n" + printf "fi\n" +} > "./${ID}/opt/apps/${ID}/files/start.sh" + +case $? in + 0) + echo "[STATUS] 创建并写入内容到 start.sh 文件成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 寻找 .desktop 文件 +DESKTOP_FILE=`find "./${ID}/opt/apps/${ID}/files/bin/" -type f -name "*.desktop"` +DESKTOP_FILE=`realpath "${DESKTOP_FILE}"` + +case $? in + 0) + echo "[STATUS] DESKTOP_FILE=${DESKTOP_FILE}" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 将 .desktop 文件复制到 applications/ 并修改文件名 +cp "${DESKTOP_FILE}" "./${ID}/opt/apps/${ID}/entries/applications/" +DESKTOP_FILE_NAME="$(ls "./${ID}/opt/apps/${ID}/entries/applications/")" +mv "./${ID}/opt/apps/${ID}/entries/applications/${DESKTOP_FILE_NAME}" "./${ID}/opt/apps/${ID}/entries/applications/${ID}.desktop" + +case $? in + 0) + echo "[STATUS] 成功将 ${DESKTOP_FILE_NAME} 文件复制到 applications/ 并修改文件名为 ${ID}.desktop" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 修改 .desktop 文件的 Exec 字段 +sed -i "s#^Exec=.*#Exec=/opt/apps/${ID}/files/start.sh %f#" "./${ID}/opt/apps/${ID}/entries/applications/${ID}.desktop" + +case $? in + 0) + echo "[STATUS] 成功修改 .desktop 文件的 Exec 字段" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 获取 Installed-Size +INSTALLED_SIZE=$(du -sk "./${ID}/opt/apps/${ID}/" | awk '{print $1}') + +case $? in + 0) + echo "[STATUS] INSTALL_SIZE=${INSTALLED_SIZE}" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 找到 png 文件,检测到分辨率不足 512x512 则超分辨率 + +# 获取 icon 文件 +PNG_FILE_NAME="$(basename ${DESKTOP_FILE_NAME} .desktop).png" +SVG_FILE_NAME="$(basename ${DESKTOP_FILE_NAME} .desktop).svg" +PNG_FILE="./${ID}/opt/apps/${ID}/files/bin/${PNG_FILE_NAME}" +SVG_FILE="./${ID}/opt/apps/${ID}/files/bin/${SVG_FILE_NAME}" + +if [[ -L "${SVG_FILE}" ]]; then + SVG_FILE="$(readlink -f "${SVG_FILE}")" + cp "${SVG_FILE}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalabel/apps/" + mv "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalabel/apps/${SVG_FILE_NAME}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalabel/apps/${ID}.svg" + echo "[STATUS] 找到 svg 图标文件" +elif [[ -L "${PNG_FILE}" ]]; then + PNG_FILE="$(readlink -f "${PNG_FILE}")" + cp "${PNG_FILE}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/512x512/apps/" + mv "./${ID}/opt/apps/${ID}/entries/icons/hicolor/512x512/apps/${PNG_FILE_NAME}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/512x512/apps/${ID}.png" + echo "[STATUS] 找到 png 图标文件" +elif [[ -e "${SVG_FILE}" ]]; then + cp "${SVG_FILE}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalabel/apps/" + mv "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalabel/apps/${SVG_FILE_NAME}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalabel/apps/${ID}.svg" + echo "[STATUS] 找到 svg 图标文件" +elif [[ -e "${PNG_FILE}" ]]; then + cp "${PNG_FILE}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/512x512/apps/" + mv "./${ID}/opt/apps/${ID}/entries/icons/hicolor/512x512/apps/${PNG_FILE_NAME}" "./${ID}/opt/apps/${ID}/entries/icons/hicolor/scalabel/apps/${ID}.png" + echo "[STATUS] 找到 png 图标文件" +else + echo "[STATUS] 没有找到图标文件" +fi + +# 修改 .desktop 文件的 Icon 字段 +sed -i "s#^Icon=.*#Icon=${ID}#" "./${ID}/opt/apps/${ID}/entries/applications/${ID}.desktop" + +case $? in + 0) + echo "[STATUS] 成功修改 .desktop 文件的 Icon 字段" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 从 .desktop 文件的 comment 获取 description +DESCRIPTION="$(grep '^Comment=' "${DESKTOP_FILE}" | awk -F'=' '{print $2}')" +DESCRIPTION="${DESCRIPTION##*([[:space:]])}" +DESCRIPTION="${DESCRIPTION%%*([[:space:]])}" + +case $? in + 0) + echo "[STATUS] DESCRIPTION=${DESCRIPTION}" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 从 .desktop 文件的 Categories 获取 section +SECTION="utils" + +# 写入 control 文件 +{ + printf "Package: ${ID}\n" + printf "Version: ${VERSION}\n" + printf "Section: ${SECTION}\n" + printf "Priority: optional\n" + printf "Architecture: amd64\n" + printf "Installed-Size: ${INSTALLED_SIZE}\n" + printf "Maintainer: ${MAINTAINER} <${MAIL}>\n" + printf "Description: ${DESCRIPTION}\n" +} > "./${ID}/DEBIAN/control" + +case $? in + 0) + echo "[STATUS] 写入 control 文件成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 更改用户组和权限 +echo "${PASSWORD}" | sudo -S chown -R root:root "./${ID}" +echo "${PASSWORD}" | sudo -S chmod -R 755 "./${ID}" + +case $? in + 0) + echo "[STATUS] 更改用户组和权限成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac + +# 生成 deb 包 +printf "[STATUS] " +zenity --info --text="正在生成 deb 包,生成结束后会弹出信息框,请耐心等待" & +dpkg-deb --build "./${ID}" . & +pid=$! + +wait ${pid} + +case $? in + 0) + echo "[STATUS] 生成 deb 包成功" + zenity --info --text="生成 deb 包成功" + ;; + *) + echo "[ERROR] 发生意外错误" + exit -1 + ;; +esac