#!/usr/bin/env bash # 共享 dm-server 薄入口:读取 deps/development-manager 的 gitlink 钉住提交, # 按该提交构建并缓存 dm-server,再 exec 其子命令(agent-exec、task、governance)。执行语义与退出码以该二进制为准。 set -euo pipefail root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P) dm="$root/deps/development-manager" die() { echo "dm: $*" >&2; exit 2; } # 1. 钉住版本只来自索引中的 gitlink(mode 160000),不读取工作区文件。 entry=$(git -C "$root" ls-files -s -- deps/development-manager 2>/dev/null || true) [ -n "$entry" ] || die "索引中缺少 deps/development-manager 的 gitlink,无法确定钉住的 DM 版本" read -r mode pin _stage _path <<<"$entry" [ "$mode" = 160000 ] || die "deps/development-manager 不是 gitlink(mode=$mode)" [[ "$pin" =~ ^[0-9a-f]{40}$ ]] || die "gitlink 提交格式无效:$pin" # 2. 检出必须存在且确为 DM 独立仓库(避免 git -C 误解析到外层仓库),HEAD 必须等于钉住提交。 [ -e "$dm/.git" ] || die "deps/development-manager 未检出;请按钉住提交 $pin 检出该 gitlink" top=$(git -C "$dm" rev-parse --show-toplevel 2>/dev/null || true) [ -n "$top" ] && [ "$top" = "$(cd "$dm" && pwd -P)" ] \ || die "deps/development-manager 不是独立检出;请按钉住提交 $pin 检出该 gitlink" head=$(git -C "$dm" rev-parse HEAD 2>/dev/null || true) [ "$head" = "$pin" ] \ || die "deps/development-manager HEAD(${head:-未知})与钉住提交 $pin 不一致;请按钉住提交检出" # 3. 检出工作树必须干净(忽略嵌套 submodule 状态)。 dirty=$(git -C "$dm" status --porcelain --ignore-submodules=all) \ || die "无法读取 deps/development-manager 的工作树状态" [ -z "$dirty" ] || die "deps/development-manager 存在未提交改动,拒绝运行(请先清理该检出)" # 4. 二进制按钉住提交缓存;缺失时在缓存目录内临时构建,完成后原子改名,避免留下半成品。 cache="${DM_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/development-manager/dm-server}" bin="$cache/dm-server-$pin" if [ ! -x "$bin" ]; then command -v go >/dev/null 2>&1 || die "缺少 go,无法构建 dm-server($pin)" mkdir -p "$cache" cache=$(cd "$cache" && pwd -P) bin="$cache/dm-server-$pin" work=$(mktemp -d "$cache/build-$pin.XXXXXX") if ! (cd "$dm" && go build -trimpath -o "$work/dm-server" ./cmd/dm-server); then rm -rf "$work" die "构建 dm-server 失败($pin)" fi mv -f "$work/dm-server" "$bin" rm -rf "$work" fi exec "$bin" "$@"