Files
amber-pm/apm-convert.sh
2025-10-22 00:05:13 +08:00

283 lines
7.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# APM软件包转换器 - 将DEB包转换为APM格式
log.warn() { echo -e "[\e[33mWARN\e[0m]: \e[1m$*\e[0m"; }
log.error() { echo -e "[\e[31mERROR\e[0m]: \e[1m$*\e[0m"; }
log.info() { echo -e "[\e[96mINFO\e[0m]: \e[1m$*\e[0m"; }
log.debug() { echo -e "[\e[32mDEBUG\e[0m]: \e[1m$*\e[0m"; }
# 显示用法信息
usage() {
echo "用法: apm-convert-deb --base <basename> <deb文件路径> [--pkgname <包名>] [--version <版本号>]"
echo ""
echo "参数说明:"
echo " --basename 必填参数,指定基础环境名称"
echo " deb文件路径 必填参数要转换的DEB文件路径"
echo " --pkgname 可选参数指定新包的包名默认使用原DEB包名"
echo " --version 可选参数,指定新包的版本号(默认在原版本后追加'-apm'"
echo ""
echo "示例:"
echo " apm-convert-deb --base amber-pm-trixie /path/to/package.deb"
echo " apm-convert-deb --base amber-pm-trixie /path/to/package.deb --pkgname new-pkg --version 1.0.0"
}
# 检查参数数量
if [ $# -lt 3 ]; then
log.error "错误:参数不足"
usage
exit 1
fi
# 解析参数
BASENAME=""
DEB_PATH=""
PKGNAME=""
VERSION=""
# 参数解析
while [ $# -gt 0 ]; do
case $1 in
--base)
BASENAME="$2"
shift 2
;;
--pkgname)
PKGNAME="$2"
shift 2
;;
--version)
VERSION="$2"
shift 2
;;
*)
if [ -z "$DEB_PATH" ] && [ -f "$1" ]; then
DEB_PATH="$1"
shift
else
log.error "错误未知参数或无效的DEB文件路径: $1"
usage
exit 1
fi
;;
esac
done
# 检查必填参数
if [ -z "$BASENAME" ] || [ -z "$DEB_PATH" ]; then
log.error "错误:--basename 和 DEB文件路径 为必填参数"
usage
exit 1
fi
# 检查DEB文件是否存在
if [ ! -f "$DEB_PATH" ]; then
log.error "错误DEB文件不存在: $DEB_PATH"
exit 1
fi
log.info "开始转换DEB包: $DEB_PATH"
log.info "基础环境: $BASENAME"
# 1. 创建临时工作目录
CRAFT_DIR="$HOME/apm-craft-$$"
log.info "创建临时工作目录: $CRAFT_DIR"
mkdir -p "$CRAFT_DIR"/{core,work,mergedir}
# 设置环境变量
export CRAFT_DIR
# 检查是否已挂载,避免重复挂载
cleanup_mount() {
if mountpoint -q "$CRAFT_DIR/mergedir"; then
log.info "解除挂载: $CRAFT_DIR/mergedir"
sudo umount "$CRAFT_DIR/mergedir" || true
fi
}
# 清理函数
cleanup() {
log.info "开始清理..."
cleanup_mount
if [ -d "$CRAFT_DIR" ]; then
log.info "删除临时目录: $CRAFT_DIR"
sudo rm -rf "$CRAFT_DIR"
fi
}
# 设置退出时清理
trap cleanup EXIT
# 2. 进行融合挂载
log.info "正在进行融合挂载..."
ACE_ENV_PATH="/var/lib/apm/apm/files/ace-env/var/lib/apm/${BASENAME}/files/ace-env"
if [ ! -d "$ACE_ENV_PATH" ]; then
log.error "错误:基础环境路径不存在: $ACE_ENV_PATH"
exit 1
fi
sudo mount -t overlay overlay \
-o "lowerdir=$ACE_ENV_PATH,upperdir=$CRAFT_DIR/core/,workdir=$CRAFT_DIR/work/" \
"$CRAFT_DIR/mergedir"
log.info "挂载完成"
# 3. 在融合环境中安装DEB包
log.info "在融合环境中安装DEB包..."
# 更新包列表
export chrootEnvPath="$CRAFT_DIR/mergedir"
sudo -E /var/lib/apm/apm/files/ace-run-pkg aptss update
# 安装DEB包
sudo -E /var/lib/apm/apm/files/ace-run-pkg aptss install "$DEB_PATH" -y
log.info "DEB包安装完成"
# 4. 检查原DEB包信息
log.info "检查原DEB包信息..."
ORIG_PKGNAME=$(dpkg -f "$DEB_PATH" Package)
ORIG_VERSION=$(dpkg -f "$DEB_PATH" Version)
log.info "原包名: $ORIG_PKGNAME"
log.info "原版本: $ORIG_VERSION"
# 设置新包名和版本
NEW_PKGNAME="${PKGNAME:-$ORIG_PKGNAME}"
NEW_VERSION="${VERSION:-${ORIG_VERSION}-apm}"
log.info "新包名: $NEW_PKGNAME"
log.info "新版本: $NEW_VERSION"
# 5. 创建新的DEB包结构
log.info "创建新的APM包结构..."
PKG_BUILD_DIR="$CRAFT_DIR/new-pkg"
mkdir -p "$PKG_BUILD_DIR/DEBIAN"
mkdir -p "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME"/{entries,files}
# 创建info文件
echo "$BASENAME" > "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/info"
# 创建postinst脚本
cat > "$PKG_BUILD_DIR/DEBIAN/postinst" << 'EOF'
#!/bin/bash
PACKAGE_NAME="$DPKG_MAINTSCRIPT_PACKAGE"
if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then
echo "清理卸载残留"
rm -rf "/var/lib/apm/$PACKAGE_NAME"
else
echo "非卸载,跳过清理"
fi
EOF
chmod +x "$PKG_BUILD_DIR/DEBIAN/postinst"
# 6. 提取原DEB包内容并处理
log.info "提取原DEB包内容..."
EXTRACT_DIR="$CRAFT_DIR/extract"
mkdir -p "$EXTRACT_DIR"
# 解压DEB包
dpkg -x "$DEB_PATH" "$EXTRACT_DIR"
# 处理.desktop文件
find "$EXTRACT_DIR" -name "*.desktop" | while read -r desktop_file; do
log.info "处理桌面文件: $desktop_file"
# 在Exec和TryExec行前追加 "apm run $NEW_PKGNAME"
# 处理Exec行
if grep -q '^Exec=' "$desktop_file"; then
sed -i 's/^Exec=\(.*\)$/Exec=apm run '"$NEW_PKGNAME"' \1/' "$desktop_file"
fi
# 处理TryExec行
if grep -q '^TryExec=' "$desktop_file"; then
sed -i 's/^TryExec=\(.*\)$/TryExec=apm run '"$NEW_PKGNAME"' \1/' "$desktop_file"
fi
icon_line=$(grep "^Icon=" "$desktop_file")
if [[ "$icon_line" == "Icon=/"* ]]; then
# 单引号包裹不变部分,双引号包裹变量部分
sed -i 's|^Icon=/|Icon=/var/lib/apm/apm/files/ace-env/var/lib/apm/'"$NEW_PKGNAME"'/files/core/|' "$desktop_file"
fi
# 检查修改结果
if grep -q "apm run $NEW_PKGNAME" "$desktop_file"; then
log.info "桌面文件修改成功"
log.debug "修改后的Exec行: $(grep '^Exec=' "$desktop_file" || echo "未找到")"
log.debug "修改后的TryExec行: $(grep '^TryExec=' "$desktop_file" || echo "未找到")"
else
log.warn "桌面文件可能未正确修改: $desktop_file"
fi
if ! grep -q "X-APM-APPID" "$desktop_file"; then
log.info "追加 X-APM-APPID"
echo "X-APM-APPID=$NEW_PKGNAME" >> $desktop_file
fi
# # 复制到entries目录
# rel_path="${desktop_file#$EXTRACT_DIR}"
# target_dir="$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/entries/$(dirname "$rel_path")"
# mkdir -p "$target_dir"
# cp "$desktop_file" "$target_dir/"
done
# 复制/usr/share/内容到entries
if [ -d "$EXTRACT_DIR/usr/share" ]; then
log.info "复制/usr/share/内容..."
cp -r "$EXTRACT_DIR/usr/share/"* "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/entries/"
fi
# 复制/opt/apps/内容(如果存在)
if [ -d "$EXTRACT_DIR/opt/apps/$ORIG_PKGNAME/entries" ]; then
log.info "复制/opt/apps/$ORIG_PKGNAME/entries内容..."
cp -r "$EXTRACT_DIR/opt/apps/$ORIG_PKGNAME/entries/"* "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/entries/"
fi
# 7. 复制融合环境文件
log.info "复制融合环境文件..."
sudo cp -r "$CRAFT_DIR"/{core,work} "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/files/"
# 设置文件权限
sudo chmod -R 755 "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/files/"
# 8. 解除挂载
log.info "解除挂载..."
cleanup_mount
# 9. 打包新的DEB包
log.info "打包新的APM包..."
calculate_directory_size() {
local dir="$1"
if [ -d "$dir" ]; then
du -sk "$dir" | cut -f1
else
echo "0"
fi
}
# 创建control文件
cat > "${PKG_BUILD_DIR}/DEBIAN/control" << EOF
Package: $NEW_PKGNAME
Version: $NEW_VERSION
Architecture: amd64
Maintainer: APM Converter <apm@localhost>
Depends: $BASENAME
Installed-Size: $(calculate_directory_size $PKG_BUILD_DIR)
Description: APM converted package from $DEB_PATH
This package was automatically converted from the original deb package.
EOF
fakeroot dpkg-deb --build "$PKG_BUILD_DIR" .
log.info "转换完成!"
log.info "生成的APM包: $OUTPUT_DEB"
log.info "包名: $NEW_PKGNAME"
log.info "版本: $NEW_VERSION"
log.info "依赖: $BASENAME"