#!/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