create-new-feature.sh 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #!/usr/bin/env bash
  2. set -e
  3. JSON_MODE=false
  4. ARGS=()
  5. for arg in "$@"; do
  6. case "$arg" in
  7. --json) JSON_MODE=true ;;
  8. --help|-h) echo "Usage: $0 [--json] [--skip-check] <feature_description>"; exit 0 ;;
  9. *) ARGS+=("$arg") ;;
  10. esac
  11. done
  12. FEATURE_DESCRIPTION="${ARGS[*]}"
  13. if [ -z "$FEATURE_DESCRIPTION" ]; then
  14. echo "Usage: $0 [--json] <feature_description>" >&2
  15. exit 1
  16. fi
  17. # 添加分支管理检查 - 可以通过 --skip-check 跳过
  18. SKIP_BRANCH_CHECK=false
  19. for arg in "$@"; do
  20. case "$arg" in
  21. --skip-check) SKIP_BRANCH_CHECK=true ;;
  22. esac
  23. done
  24. # Function to find the repository root by searching for existing project markers
  25. find_repo_root() {
  26. local dir="$1"
  27. while [ "$dir" != "/" ]; do
  28. if [ -d "$dir/.git" ] || [ -d "$dir/.specify" ]; then
  29. echo "$dir"
  30. return 0
  31. fi
  32. dir="$(dirname "$dir")"
  33. done
  34. return 1
  35. }
  36. # Resolve repository root. Prefer git information when available, but fall back
  37. # to searching for repository markers so the workflow still functions in repositories that
  38. # were initialised with --no-git.
  39. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  40. if git rev-parse --show-toplevel >/dev/null 2>&1; then
  41. REPO_ROOT=$(git rev-parse --show-toplevel)
  42. HAS_GIT=true
  43. else
  44. REPO_ROOT="$(find_repo_root "$SCRIPT_DIR")"
  45. if [ -z "$REPO_ROOT" ]; then
  46. echo "Error: Could not determine repository root. Please run this script from within the repository." >&2
  47. exit 1
  48. fi
  49. HAS_GIT=false
  50. fi
  51. cd "$REPO_ROOT"
  52. # 分支管理检查 (除非跳过)
  53. if [ "$SKIP_BRANCH_CHECK" = false ] && [ "$HAS_GIT" = true ]; then
  54. MANAGE_SCRIPT="$REPO_ROOT/.specify/scripts/bash/manage-branches.sh"
  55. if [ -x "$MANAGE_SCRIPT" ]; then
  56. echo "🔍 检查分支状态..."
  57. if ! "$MANAGE_SCRIPT" --check; then
  58. echo ""
  59. echo "💡 建议先清理现有分支,或使用 --skip-check 跳过检查"
  60. echo "运行: $MANAGE_SCRIPT --cleanup"
  61. exit 1
  62. fi
  63. echo ""
  64. fi
  65. fi
  66. SPECS_DIR="$REPO_ROOT/specs"
  67. mkdir -p "$SPECS_DIR"
  68. HIGHEST=0
  69. if [ -d "$SPECS_DIR" ]; then
  70. for dir in "$SPECS_DIR"/*; do
  71. [ -d "$dir" ] || continue
  72. dirname=$(basename "$dir")
  73. number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0")
  74. number=$((10#$number))
  75. if [ "$number" -gt "$HIGHEST" ]; then HIGHEST=$number; fi
  76. done
  77. fi
  78. NEXT=$((HIGHEST + 1))
  79. FEATURE_NUM=$(printf "%03d" "$NEXT")
  80. BRANCH_NAME=$(echo "$FEATURE_DESCRIPTION" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//')
  81. WORDS=$(echo "$BRANCH_NAME" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//')
  82. BRANCH_NAME="${FEATURE_NUM}-${WORDS}"
  83. if [ "$HAS_GIT" = true ]; then
  84. git checkout -b "$BRANCH_NAME"
  85. else
  86. >&2 echo "[specify] Warning: Git repository not detected; skipped branch creation for $BRANCH_NAME"
  87. fi
  88. FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME"
  89. mkdir -p "$FEATURE_DIR"
  90. TEMPLATE="$REPO_ROOT/.specify/templates/spec-template.md"
  91. SPEC_FILE="$FEATURE_DIR/spec.md"
  92. if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi
  93. # Set the SPECIFY_FEATURE environment variable for the current session
  94. export SPECIFY_FEATURE="$BRANCH_NAME"
  95. if $JSON_MODE; then
  96. printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
  97. else
  98. echo "BRANCH_NAME: $BRANCH_NAME"
  99. echo "SPEC_FILE: $SPEC_FILE"
  100. echo "FEATURE_NUM: $FEATURE_NUM"
  101. echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
  102. fi