common.sh 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/usr/bin/env bash
  2. # Common functions and variables for all scripts
  3. # Get repository root, with fallback for non-git repositories
  4. get_repo_root() {
  5. if git rev-parse --show-toplevel >/dev/null 2>&1; then
  6. git rev-parse --show-toplevel
  7. else
  8. # Fall back to script location for non-git repos
  9. local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  10. (cd "$script_dir/../../.." && pwd)
  11. fi
  12. }
  13. # Get current branch, with fallback for non-git repositories
  14. get_current_branch() {
  15. # First check if SPECIFY_FEATURE environment variable is set
  16. if [[ -n "${SPECIFY_FEATURE:-}" ]]; then
  17. echo "$SPECIFY_FEATURE"
  18. return
  19. fi
  20. # Then check git if available
  21. if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then
  22. git rev-parse --abbrev-ref HEAD
  23. return
  24. fi
  25. # For non-git repos, try to find the latest feature directory
  26. local repo_root=$(get_repo_root)
  27. local specs_dir="$repo_root/specs"
  28. if [[ -d "$specs_dir" ]]; then
  29. local latest_feature=""
  30. local highest=0
  31. for dir in "$specs_dir"/*; do
  32. if [[ -d "$dir" ]]; then
  33. local dirname=$(basename "$dir")
  34. if [[ "$dirname" =~ ^([0-9]{3})- ]]; then
  35. local number=${BASH_REMATCH[1]}
  36. number=$((10#$number))
  37. if [[ "$number" -gt "$highest" ]]; then
  38. highest=$number
  39. latest_feature=$dirname
  40. fi
  41. fi
  42. fi
  43. done
  44. if [[ -n "$latest_feature" ]]; then
  45. echo "$latest_feature"
  46. return
  47. fi
  48. fi
  49. echo "main" # Final fallback
  50. }
  51. # Check if we have git available
  52. has_git() {
  53. git rev-parse --show-toplevel >/dev/null 2>&1
  54. }
  55. check_feature_branch() {
  56. local branch="$1"
  57. local has_git_repo="$2"
  58. # For non-git repos, we can't enforce branch naming but still provide output
  59. if [[ "$has_git_repo" != "true" ]]; then
  60. echo "[specify] Warning: Git repository not detected; skipped branch validation" >&2
  61. return 0
  62. fi
  63. if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then
  64. echo "ERROR: Not on a feature branch. Current branch: $branch" >&2
  65. echo "Feature branches should be named like: 001-feature-name" >&2
  66. return 1
  67. fi
  68. return 0
  69. }
  70. get_feature_dir() { echo "$1/specs/$2"; }
  71. get_feature_paths() {
  72. local repo_root=$(get_repo_root)
  73. local current_branch=$(get_current_branch)
  74. local has_git_repo="false"
  75. if has_git; then
  76. has_git_repo="true"
  77. fi
  78. local feature_dir=$(get_feature_dir "$repo_root" "$current_branch")
  79. cat <<EOF
  80. REPO_ROOT='$repo_root'
  81. CURRENT_BRANCH='$current_branch'
  82. HAS_GIT='$has_git_repo'
  83. FEATURE_DIR='$feature_dir'
  84. FEATURE_SPEC='$feature_dir/spec.md'
  85. IMPL_PLAN='$feature_dir/plan.md'
  86. TASKS='$feature_dir/tasks.md'
  87. RESEARCH='$feature_dir/research.md'
  88. DATA_MODEL='$feature_dir/data-model.md'
  89. QUICKSTART='$feature_dir/quickstart.md'
  90. CONTRACTS_DIR='$feature_dir/contracts'
  91. EOF
  92. }
  93. check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; }
  94. check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; }