#!/usr/bin/env sh set -eu # Sync standards snapshot to project root. # - Copies /.agents -> /.agents/tsl # - Updates /.gitattributes (managed block by default) # Existing targets are backed up before overwrite. SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)" SRC="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd -P)" ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || pwd)" ROOT="$(CDPATH= cd -- "$ROOT" && pwd -P)" AGENTS_SRC="$SRC/.agents" GITATTR_SRC="$SRC/.gitattributes" if [ ! -d "$AGENTS_SRC" ]; then echo "ERROR: Standards snapshot not found at $AGENTS_SRC" >&2 echo "Run: git subtree add --prefix --squash" >&2 exit 1 fi timestamp="$(date +%Y%m%d%H%M%S 2>/dev/null || echo bak)" if [ "$SRC" = "$ROOT" ]; then echo "Skip: snapshot root equals project root." echo "Done." exit 0 fi : "${AGENTS_NS:=tsl}" case "$AGENTS_NS" in ""|*/*|*\\*|*..*) echo "ERROR: invalid AGENTS_NS=$AGENTS_NS" >&2 exit 1 ;; esac AGENTS_ROOT="$ROOT/.agents" AGENTS_DST="$AGENTS_ROOT/$AGENTS_NS" mkdir -p "$AGENTS_ROOT" if [ -e "$AGENTS_DST" ]; then mv "$AGENTS_DST" "$AGENTS_ROOT/$AGENTS_NS.bak.$timestamp" echo "Backed up existing $AGENTS_NS agents -> $AGENTS_NS.bak.$timestamp" fi cp -R "$AGENTS_SRC" "$AGENTS_DST" echo "Synced .agents/$AGENTS_NS from standards." AGENTS_INDEX="$AGENTS_ROOT/index.md" if [ ! -f "$AGENTS_INDEX" ]; then cat >"$AGENTS_INDEX" <<'EOF' # .agents(多语言) 本目录用于存放仓库级/语言级的代理规则集。 建议约定: - `.agents/tsl/`:TSL 相关规则集(由 `sync_standards.*` 同步;适用于 `.tsl`/`.tsf`) - `.agents/cpp/`、`.agents/python/` 等:其他语言的规则集(按需增加) 规则发生冲突时,建议以“更靠近代码的目录规则更具体”为准。 入口建议从: - `.agents/tsl/index.md`(TSL 规则集入口) - `docs/standards/tsl/docs/tsl/`(TSL 人类开发规范快照,推荐 subtree/vendoring 到该路径) EOF echo "Created .agents/index.md" fi echo "Synced agents ruleset to $AGENTS_DST." GITATTR_DST="$ROOT/.gitattributes" if [ -f "$GITATTR_SRC" ]; then : "${SYNC_GITATTR_MODE:=block}" case "$SYNC_GITATTR_MODE" in skip) echo "Skip: .gitattributes sync (SYNC_GITATTR_MODE=skip)." ;; overwrite) if [ "$(CDPATH= cd -- "$(dirname -- "$GITATTR_SRC")" && pwd -P)/$(basename -- "$GITATTR_SRC")" = "$GITATTR_DST" ]; then echo "Skip: .gitattributes source equals destination." else if [ -e "$GITATTR_DST" ]; then mv "$GITATTR_DST" "$ROOT/.gitattributes.bak.$timestamp" echo "Backed up existing .gitattributes -> .gitattributes.bak.$timestamp" fi cp "$GITATTR_SRC" "$GITATTR_DST" echo "Synced .gitattributes from standards (overwrite)." fi ;; block) begin="# BEGIN tsl-playbook .gitattributes" end="# END tsl-playbook .gitattributes" if [ -e "$GITATTR_DST" ]; then mv "$GITATTR_DST" "$ROOT/.gitattributes.bak.$timestamp" echo "Backed up existing .gitattributes -> .gitattributes.bak.$timestamp" fi tmp="${GITATTR_DST}.tmp.${timestamp}" if [ -f "$ROOT/.gitattributes.bak.$timestamp" ]; then src_dst="$ROOT/.gitattributes.bak.$timestamp" else src_dst="" fi if [ -n "$src_dst" ]; then awk -v begin="$begin" -v end="$end" -v src="$GITATTR_SRC" ' function emit_src() { print begin while ((getline line < src) > 0) print line close(src) print end } BEGIN { in_block=0; done=0 } $0 == begin { in_block=1; if (!done) { emit_src(); done=1 } ; next } $0 == end { in_block=0; next } !in_block { print } END { if (!done) { if (NR > 0) print "" emit_src() } } ' "$src_dst" >"$tmp" else { printf "%s\n" "$begin" cat "$GITATTR_SRC" printf "\n%s\n" "$end" } >"$tmp" fi mv "$tmp" "$GITATTR_DST" echo "Updated .gitattributes from standards (managed block)." ;; *) echo "ERROR: invalid SYNC_GITATTR_MODE=$SYNC_GITATTR_MODE (use block|overwrite|skip)" >&2 exit 1 ;; esac fi echo "Done."