From 18af9bf4b6ac7342d431b4d8ec4a03a7c7d8018a Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 14 Nov 2025 03:31:19 +0000 Subject: [PATCH] update src/usr/bin/amber-pm-convert. Signed-off-by: shenmo --- src/usr/bin/amber-pm-convert | 471 +++++++++++++++++++---------------- 1 file changed, 252 insertions(+), 219 deletions(-) diff --git a/src/usr/bin/amber-pm-convert b/src/usr/bin/amber-pm-convert index 3b8a050..3db20c0 100755 --- a/src/usr/bin/amber-pm-convert +++ b/src/usr/bin/amber-pm-convert @@ -257,197 +257,251 @@ if [ "$MANUAL_MODE" = true ]; then log.warn "ace-run-pkg shell 退出或出现错误,继续脚本..." } log.info "用户已退出手动 shell,脚本将继续。" - - # 新增:在 manual 模式且无 DEB 文件的情况下,查找并复制桌面文件和图标 + # 如果没有 DEB,询问是否要进行后续打包(允许返回 shell) if [ -z "$DEB_PATH" ]; then - # 第一阶段:选择并复制桌面文件 while true; do echo "" - log.info "=== 桌面文件处理 ===" - # 查找所有 .desktop 文件 - DESKTOP_FILES=() - while IFS= read -r -d '' file; do - DESKTOP_FILES+=("$file") - done < <(find "$CRAFT_DIR/core/usr/share" -name "*.desktop" -type f -print0 2>/dev/null || true) - - if [ ${#DESKTOP_FILES[@]} -eq 0 ]; then - log.warn "在 $CRAFT_DIR/core/usr/share 中未找到 .desktop 文件" - break - fi - - log.info "找到以下桌面文件:" - for i in "${!DESKTOP_FILES[@]}"; do - echo " [$((i+1))] ${DESKTOP_FILES[$i]}" - done - - read -r -p "请选择要复制的桌面文件编号(输入多个编号用空格分隔,输入 0 跳过): " selection - - if [ "$selection" = "0" ]; then - log.info "跳过桌面文件复制" - break - fi - - # 处理选择 - IFS=' ' read -ra SELECTED_INDEXES <<< "$selection" - if [ ${#SELECTED_INDEXES[@]} -gt 0 ]; then - # 创建 entries 目录 - mkdir -p "$CRAFT_DIR/new-pkg/var/lib/apm/${NEW_PKGNAME}/entries/applications" 2>/dev/null || true - - for idx in "${SELECTED_INDEXES[@]}"; do - if [[ "$idx" =~ ^[0-9]+$ ]] && [ "$idx" -ge 1 ] && [ "$idx" -le ${#DESKTOP_FILES[@]} ]; then - desktop_file="${DESKTOP_FILES[$((idx-1))]}" - # 如果是符号链接,找到源文件 - if [ -L "$desktop_file" ]; then - target_file=$(readlink -f "$desktop_file" 2>/dev/null || echo "$desktop_file") - log.info "处理符号链接: $desktop_file -> $target_file" - desktop_file="$target_file" - fi - - if [ -f "$desktop_file" ]; then - filename=$(basename "$desktop_file") - dest_path="$CRAFT_DIR/new-pkg/var/lib/apm/${NEW_PKGNAME}/entries/applications/$filename" - log.info "复制桌面文件: $desktop_file -> $dest_path" - cp "$desktop_file" "$dest_path" - - # 处理桌面文件内容 - if command -v busybox >/dev/null 2>&1; then - busybox dos2unix "$dest_path" 2>/dev/null || true - else - dos2unix "$dest_path" 2>/dev/null || true - fi - - # 修改 Exec 行 - if grep -q '^Exec=' "$dest_path"; then - sed -i "s|^Exec=\(.*\)$|Exec=apm run ${NEW_PKGNAME:-$ORIG_PKGNAME} \1|" "$dest_path" - fi - - # 删除 TryExec 行 - if grep -q '^TryExec=' "$dest_path"; then - sed -i '/^TryExec=/d' "$dest_path" - log.info "已删除 TryExec 行" - fi - - # 添加 X-APM-APPID - if ! grep -q "X-APM-APPID" "$dest_path"; then - echo "X-APM-APPID=${NEW_PKGNAME:-$ORIG_PKGNAME}" >> "$dest_path" - fi - - log.info "桌面文件处理完成: $filename" - fi - done - break - else - log.warn "无效的选择,请重新输入" - fi - done - - # 第二阶段:选择并复制图标文件 - while true; do - echo "" - log.info "=== 图标文件处理 ===" - # 查找所有图标文件 - ICON_FILES=() - while IFS= read -r -d '' file; do - ICON_FILES+=("$file") - done < <(find "$CRAFT_DIR/core/usr/share" \( -name "*.png" -o -name "*.svg" -o -name "*.xpm" \) -type f -print0 2>/dev/null || true) - - if [ ${#ICON_FILES[@]} -eq 0 ]; then - log.warn "在 $CRAFT_DIR/core/usr/share 中未找到图标文件" - break - fi - - log.info "找到以下图标文件:" - for i in "${!ICON_FILES[@]}"; do - echo " [$((i+1))] ${ICON_FILES[$i]}" - done - - read -r -p "请选择要复制的图标文件编号(输入多个编号用空格分隔,输入 0 跳过): " selection - - if [ "$selection" = "0" ]; then - log.info "跳过图标文件复制" - break - fi - - # 处理选择 - IFS=' ' read -ra SELECTED_INDEXES <<< "$selection" - if [ ${#SELECTED_INDEXES[@]} -gt 0 ]; then - mkdir -p "$CRAFT_DIR/new-pkg/var/lib/apm/${NEW_PKGNAME}/entries/icons" 2>/dev/null || true - - for idx in "${SELECTED_INDEXES[@]}"; do - if [[ "$idx" =~ ^[0-9]+$ ]] && [ "$idx" -ge 1 ] && [ "$idx" -le ${#ICON_FILES[@]} ]; then - icon_file="${ICON_FILES[$((idx-1))]}" - filename=$(basename "$icon_file") - # 按尺寸分类图标 - size_match=$(echo "$icon_file" | grep -oE '/[0-9]+x[0-9]+/' || echo "") - if [ -n "$size_match" ]; then - size=$(echo "$size_match" | sed 's|/||g') - dest_path="$CRAFT_DIR/new-pkg/var/lib/apm/${NEW_PKGNAME}/entries/icons/hicolor/$size/apps/$filename" - else - # 尝试从路径中提取尺寸 - size_dir=$(dirname "$icon_file" | grep -oE '[0-9]+x[0-9]+' || echo "") - if [ -n "$size_dir" ]; then - dest_path="$CRAFT_DIR/new-pkg/var/lib/apm/${NEW_PKGNAME}/entries/icons/hicolor/$size_dir/apps/$filename" - else - # 无法确定尺寸,放在通用目录 - dest_path="$CRAFT_DIR/new-pkg/var/lib/apm/${NEW_PKGNAME}/entries/icons/apps/$filename" - fi - fi - - # 确保目标目录存在 - mkdir -p "$(dirname "$dest_path")" - - if [ -f "$icon_file" ]; then - # 如果是符号链接,找到源文件 - if [ -L "$icon_file" ]; then - target_file=$(readlink -f "$icon_file" 2>/dev/null || echo "$icon_file") - log.info "处理符号链接: $icon_file -> $target_file" - icon_file="$target_file" - fi - - log.info "复制图标文件: $icon_file -> $dest_path" - cp "$icon_file" "$dest_path" - fi - fi - done - break - else - log.warn "无效的选择,请重新输入" - fi - done - fi - - # 询问是否要进行后续打包(允许返回 shell) - while true; do - echo "" - read -r -p "是否现在进行新 APM 包的自动打包? (y = 打包, r = 返回 shell, n = 跳过打包) [y/r/n]: " yn + read -r -p "未提供 DEB 文件。是否现在进行新 APM 包的自动打包? (y = 打包, r = 返回 shell, n = 跳过打包) [y/r/n]: " yn case "$yn" in y|Y) # 如果缺少包名或版本,交互询问 if [ -z "$NEW_PKGNAME" ]; then - read -r -p "请输入要创建的包名 (Package): " NEW_PKGNAME - fi - if [ -z "$NEW_VERSION" ] || [[ "$NEW_VERSION" == "-apm" ]]; then - read -r -p "请输入要创建的版本 (Version): " NEW_VERSION - fi - break - ;; - r|R) - log.info "返回交互 shell(使用 ace-run-pkg)。退出 shell 后再次询问。" - sudo -E chrootEnvPath="$chrootEnvPath" /var/lib/apm/apm/files/ace-run-pkg bash --login || true - ;; - n|N) - log.info "跳过自动打包。脚本结束。" - exit 0 - ;; - *) - echo "请输入 y, r, 或 n。" - ;; + read -r -p "请输入要创建的包名 (Package): " NEW_PKGNAME + fi + if [ -z "$NEW_VERSION" ] || [[ "$NEW_VERSION" == "-apm" ]]; then + read -r -p "请输入要创建的版本 (Version): " NEW_VERSION + fi + break + ;; + r|R) + log.info "返回交互 shell(使用 ace-run-pkg)。退出 shell 后再次询问。" + sudo -E chrootEnvPath="$chrootEnvPath" /var/lib/apm/apm/files/ace-run-pkg bash --login || true + ;; + n|N) + log.info "跳过自动打包。脚本结束。" + exit 0 + ;; + *) + echo "请输入 y, r, 或 n。" + ;; esac done fi fi # 到这里:非手动模式或手动模式退出后继续(如果是非手动并且有 DEB,继续原本流程) + +# 函数:查找并处理符号链接,返回实际文件路径 +resolve_symlink() { + local file="$1" + local target_dir="$2" + + if [ -L "$file" ]; then + # 获取符号链接目标 + local target=$(readlink "$file") + + # 如果目标是绝对路径,则在目标目录中查找 + if [[ "$target" == /* ]]; then + local resolved_path="$target_dir${target}" + if [ -f "$resolved_path" ]; then + echo "$resolved_path" + return 0 + fi + else + # 相对路径,在符号链接所在目录解析 + local link_dir=$(dirname "$file") + local resolved_path="$link_dir/$target" + if [ -f "$resolved_path" ]; then + echo "$resolved_path" + return 0 + fi + fi + fi + + # 如果不是符号链接或解析失败,返回原文件 + echo "$file" +} + +# 函数:交互式选择文件复制到entries目录(用于手动模式无DEB情况) +interactive_copy_entries() { + local core_dir="$CRAFT_DIR/core" + local entries_dir="$PKG_BUILD_DIR/var/lib/apm/${NEW_PKGNAME}/entries" + + log.info "开始交互式选择文件复制到 entries 目录..." + mkdir -p "$entries_dir" + + # 查找桌面文件 + local desktop_files=() + while IFS= read -r -d '' file; do + [[ -f "$file" ]] && desktop_files+=("$file") + done < <(find "$core_dir/usr/share" -name "*.desktop" -print0 2>/dev/null || true) + + # 查找图标文件 + local icon_files=() + while IFS= read -r -d '' file; do + [[ -f "$file" ]] && icon_files+=("$file") + done < <(find "$core_dir/usr/share" \( -name "*.png" -o -name "*.svg" -o -name "*.xpm" \) -print0 2>/dev/null || true) + + # 处理桌面文件 + if [ ${#desktop_files[@]} -gt 0 ]; then + log.info "找到 ${#desktop_files[@]} 个桌面文件:" + for i in "${!desktop_files[@]}"; do + local file="${desktop_files[$i]}" + local rel_path="${file#$core_dir}" + echo " $((i+1)). $rel_path" + + # 检查是否是符号链接 + if [ -L "$file" ]; then + local target=$(readlink "$file") + echo " → 符号链接指向: $target" + # 解析符号链接获取实际文件 + local resolved_file=$(resolve_symlink "$file" "$core_dir") + if [ "$resolved_file" != "$file" ] && [ -f "$resolved_file" ]; then + echo " → 解析为: ${resolved_file#$core_dir}" + desktop_files[$i]="$resolved_file" + fi + fi + done + + echo "" + read -r -p "请选择要复制的桌面文件编号(多个用逗号分隔,all=全部,none=跳过): " desktop_choice + + if [[ "$desktop_choice" =~ ^[Aa][Ll][Ll]$ ]]; then + # 复制所有桌面文件 + for file in "${desktop_files[@]}"; do + local rel_path="${file#$core_dir}" + local dest_path="$entries_dir$rel_path" + mkdir -p "$(dirname "$dest_path")" + cp -v "$file" "$dest_path" + + # 处理桌面文件内容 + process_desktop_file "$dest_path" "$NEW_PKGNAME" + done + elif [[ ! "$desktop_choice" =~ ^[Nn][Oo][Nn][Ee]$ ]] && [ -n "$desktop_choice" ]; then + # 处理选择的文件 + IFS=',' read -ra choices <<< "$desktop_choice" + for choice in "${choices[@]}"; do + choice=$(echo "$choice" | tr -d ' ') + if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#desktop_files[@]} ]; then + local idx=$((choice-1)) + local file="${desktop_files[$idx]}" + local rel_path="${file#$core_dir}" + local dest_path="$entries_dir$rel_path" + mkdir -p "$(dirname "$dest_path")" + cp -v "$file" "$dest_path" + + # 处理桌面文件内容 + process_desktop_file "$dest_path" "$NEW_PKGNAME" + else + log.warn "无效的选择: $choice" + fi + done + else + log.info "跳过桌面文件复制" + fi + else + log.info "未找到桌面文件" + fi + + # 处理图标文件 + if [ ${#icon_files[@]} -gt 0 ]; then + log.info "找到 ${#icon_files[@]} 个图标文件:" + for i in "${!icon_files[@]}"; do + local file="${icon_files[$i]}" + local rel_path="${file#$core_dir}" + echo " $((i+1)). $rel_path" + + # 检查是否是符号链接 + if [ -L "$file" ]; then + local target=$(readlink "$file") + echo " → 符号链接指向: $target" + # 解析符号链接获取实际文件 + local resolved_file=$(resolve_symlink "$file" "$core_dir") + if [ "$resolved_file" != "$file" ] && [ -f "$resolved_file" ]; then + echo " → 解析为: ${resolved_file#$core_dir}" + icon_files[$i]="$resolved_file" + fi + fi + done + + echo "" + read -r -p "请选择要复制的图标文件编号(多个用逗号分隔,all=全部,none=跳过): " icon_choice + + if [[ "$icon_choice" =~ ^[Aa][Ll][Ll]$ ]]; then + # 复制所有图标文件 + for file in "${icon_files[@]}"; do + local rel_path="${file#$core_dir}" + local dest_path="$entries_dir$rel_path" + mkdir -p "$(dirname "$dest_path")" + cp -v "$file" "$dest_path" + done + elif [[ ! "$icon_choice" =~ ^[Nn][Oo][Nn][Ee]$ ]] && [ -n "$icon_choice" ]; then + # 处理选择的文件 + IFS=',' read -ra choices <<< "$icon_choice" + for choice in "${choices[@]}"; do + choice=$(echo "$choice" | tr -d ' ') + if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#icon_files[@]} ]; then + local idx=$((choice-1)) + local file="${icon_files[$idx]}" + local rel_path="${file#$core_dir}" + local dest_path="$entries_dir$rel_path" + mkdir -p "$(dirname "$dest_path")" + cp -v "$file" "$dest_path" + else + log.warn "无效的选择: $choice" + fi + done + else + log.info "跳过图标文件复制" + fi + else + log.info "未找到图标文件" + fi +} + +# 函数:处理桌面文件内容 +process_desktop_file() { + local desktop_file="$1" + local pkgname="$2" + + log.info "处理桌面文件: $desktop_file" + + # 尝试用 busybox dos2unix(若不存在则跳过转换) + if command -v busybox >/dev/null 2>&1; then + busybox dos2unix "$desktop_file" 2>/dev/null || true + else + dos2unix "$desktop_file" 2>/dev/null || true + fi + + # 处理 Exec 行:在原有命令前追加 apm run $pkgname + if grep -q '^Exec=' "$desktop_file"; then + sed -i "s|^Exec=\(.*\)$|Exec=apm run $pkgname \1|" "$desktop_file" + fi + + # 删除 TryExec 行 + if grep -q '^TryExec=' "$desktop_file"; then + sed -i '/^TryExec=/d' "$desktop_file" + log.info "已删除 TryExec 行" + fi + + # 处理 Icon 路径(若以 / 开头) + if grep -q '^Icon=/' "$desktop_file"; then + sed -i "s|^Icon=/|Icon=/var/lib/apm/apm/files/ace-env/var/lib/apm/$pkgname/files/core/|" "$desktop_file" + fi + + # 添加 X-APM-APPID + if ! grep -q "X-APM-APPID" "$desktop_file"; then + echo "X-APM-APPID=$pkgname" >> "$desktop_file" + fi + + # 检查修改结果并打印调试 + if grep -q "apm run $pkgname" "$desktop_file"; then + log.info "桌面文件修改成功: $desktop_file" + else + log.warn "桌面文件可能未正确修改: $desktop_file" + fi +} + # 4. 如果有 DEB 文件,进行自动化的检查、解包与修改 if [ -n "$DEB_PATH" ]; then @@ -471,46 +525,12 @@ if [ -n "$DEB_PATH" ]; then dpkg -x "$DEB_PATH" "$EXTRACT_DIR" dpkg -e "$DEB_PATH" "$MODIFIED_DEB_DIR/DEBIAN" - # 处理 .desktop 文件:注意使用 while read 来避免 subshell 问题 + # 处理 .desktop 文件 DESKTOP_MODIFIED=false while IFS= read -r desktop_file; do [ -z "$desktop_file" ] && continue - log.info "处理桌面文件: $desktop_file" - # 尝试用 busybox dos2unix(若不存在则跳过转换) - if command -v busybox >/dev/null 2>&1; then - busybox dos2unix "$desktop_file" 2>/dev/null || true - else - dos2unix "$desktop_file" 2>/dev/null || true || true - fi + process_desktop_file "$desktop_file" "${NEW_PKGNAME:-$ORIG_PKGNAME}" DESKTOP_MODIFIED=true - - # 处理 Exec 行:在原有命令前追加 apm run $NEW_PKGNAME - if grep -q '^Exec=' "$desktop_file"; then - sed -i "s|^Exec=\(.*\)$|Exec=apm run ${NEW_PKGNAME:-$ORIG_PKGNAME} \1|" "$desktop_file" - fi - - # 删除 TryExec 行 - if grep -q '^TryExec=' "$desktop_file"; then - sed -i '/^TryExec=/d' "$desktop_file" - log.info "已删除 TryExec 行" - fi - - # 处理 Icon 路径(若以 / 开头) - if grep -q '^Icon=/' "$desktop_file"; then - sed -i "s|^Icon=/|Icon=/var/lib/apm/apm/files/ace-env/var/lib/apm/${NEW_PKGNAME:-$ORIG_PKGNAME}/files/core/|" "$desktop_file" - fi - - # 添加 X-APM-APPID - if ! grep -q "X-APM-APPID" "$desktop_file"; then - echo "X-APM-APPID=${NEW_PKGNAME:-$ORIG_PKGNAME}" >> "$desktop_file" - fi - - # 检查修改结果并打印调试 - if grep -q "apm run ${NEW_PKGNAME:-$ORIG_PKGNAME}" "$desktop_file"; then - log.info "桌面文件修改成功: $desktop_file" - else - log.warn "桌面文件可能未正确修改: $desktop_file" - fi done < <(find "$EXTRACT_DIR" -name "*.desktop" -print) if [ "$DESKTOP_MODIFIED" = false ]; then @@ -541,11 +561,14 @@ if [ -n "$DEB_PATH" ]; then fi log.info "修改后的 DEB 包安装完成(ssaudit)" + +fi + # 清理 apt 缓存 sudo -E chrootEnvPath="$chrootEnvPath" /var/lib/apm/apm/files/ace-run-pkg aptss clean || true sudo -E chrootEnvPath="$chrootEnvPath" /var/lib/apm/apm/files/ace-run-pkg rm -vfr /var/lib/apt/lists || true sudo -E chrootEnvPath="$chrootEnvPath" /var/lib/apm/apm/files/ace-run-pkg rm -vfr /var/lib/aptss/lists || true -fi + sudo -E chrootEnvPath="$chrootEnvPath" /var/lib/apm/apm/files/ace-run-pkg rm -vfr /var/cache/apt/* || true # 5. 创建新的 APM 包结构 log.info "创建新的APM包结构..." @@ -591,12 +614,22 @@ chmod +x "$PKG_BUILD_DIR/DEBIAN/postrm" # 6. 复制需要的文件到新的 APM 包 log.info "复制文件到新的APM包..." +# 如果是手动模式且没有DEB文件,进行交互式文件选择 +if [ "$MANUAL_MODE" = true ] && [ -z "$DEB_PATH" ]; then + interactive_copy_entries +fi + # 复制 /usr/share 内容到 entries if [ -d "$CRAFT_DIR/extract/usr/share" ]; then log.info "复制 /usr/share 内容..." - mkdir -p "$PKG_BUILD_DIR/var/lib/apm/${NEW_PKGNAME}/entries/applications" 2>/dev/null || true) - if [ -d "$CRAFT_DIR/extract/usr/share/applications" ]; then - cp -r "$CRAFT_DIR/extract/usr/share/applications/"* "$PKG_BUILD_DIR/var/lib/apm/${NEW_PKGNAME}/entries/applications/" 2>/dev/null || true + mkdir -p "$PKG_BUILD_DIR/var/lib/apm/${NEW_PKGNAME}/entries" + cp -r "$CRAFT_DIR/extract/usr/share/"* "$PKG_BUILD_DIR/var/lib/apm/${NEW_PKGNAME}/entries/" 2>/dev/null || true +fi + +# 复制 /opt/apps//entries(如果存在) +if [ -n "$ORIG_PKGNAME" ] && [ -d "$CRAFT_DIR/extract/opt/apps/$ORIG_PKGNAME/entries" ]; then + log.info "复制 /opt/apps/$ORIG_PKGNAME/entries 内容..." + cp -r "$CRAFT_DIR/extract/opt/apps/$ORIG_PKGNAME/entries/"* "$PKG_BUILD_DIR/var/lib/apm/${NEW_PKGNAME}/entries/" 2>/dev/null || true fi # 复制融合环境(core, work)到新的包内 files(以便运行时使用) @@ -615,7 +648,7 @@ cleanup_mount calculate_directory_size() { local dir="$1" if [ -d "$dir" ]; then - du -sk "$dir" | cut -f1 + du -sk "$dir" | cut -f1 else echo "0" fi