Skip to main content
Glama
common.sh6.62 kB
#!/usr/bin/env bash # Common functions and variables for all scripts # Get repository root, with fallback for non-git repositories get_repo_root() { if git rev-parse --show-toplevel >/dev/null 2>&1; then git rev-parse --show-toplevel else # Fall back to script location for non-git repos local script_dir="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" (cd "$script_dir/../../.." && pwd) fi } # Get current branch, with fallback for non-git repositories get_current_branch() { # First check if SPECIFY_FEATURE environment variable is set if [[ -n "${SPECIFY_FEATURE:-}" ]]; then echo "$SPECIFY_FEATURE" return fi # Then check git if available if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then git rev-parse --abbrev-ref HEAD return fi # For non-git repos, try to find the latest feature directory local repo_root=$(get_repo_root) local specs_dir="$repo_root/specs" if [[ -d "$specs_dir" ]]; then local latest_feature="" local highest=0 for dir in "$specs_dir"/*; do if [[ -d "$dir" ]]; then local dirname=$(basename "$dir") if [[ "$dirname" =~ ^([0-9]{3})- ]]; then local number=${BASH_REMATCH[1]} number=$((10#$number)) if [[ "$number" -gt "$highest" ]]; then highest=$number latest_feature=$dirname fi fi fi done if [[ -n "$latest_feature" ]]; then echo "$latest_feature" return fi fi echo "main" # Final fallback } # Check if we have git available has_git() { git rev-parse --show-toplevel >/dev/null 2>&1 } check_feature_branch() { local branch="$1" local has_git_repo="$2" # For non-git repos, we can't enforce branch naming but still provide output if [[ "$has_git_repo" != "true" ]]; then echo "[rainbow] Warning: Git repository not detected; skipped branch validation" >&2 return 0 fi if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then echo "ERROR: Not on a feature branch. Current branch: $branch" >&2 echo "Feature branches should be named like: 001-feature-name" >&2 return 1 fi return 0 } get_feature_dir() { echo "$1/specs/$2"; } # Find feature directory by numeric prefix instead of exact branch match # This allows multiple branches to work on the same spec (e.g., 004-fix-bug, 004-add-feature) find_feature_dir_by_prefix() { local repo_root="$1" local branch_name="$2" local specs_dir="$repo_root/specs" # Extract numeric prefix from branch (e.g., "004" from "004-whatever") if [[ ! "$branch_name" =~ ^([0-9]{3})- ]]; then # If branch doesn't have numeric prefix, fall back to exact match echo "$specs_dir/$branch_name" return fi local prefix="${BASH_REMATCH[1]}" # Search for directories in specs/ that start with this prefix local matches=() if [[ -d "$specs_dir" ]]; then for dir in "$specs_dir"/"$prefix"-*; do if [[ -d "$dir" ]]; then matches+=("$(basename "$dir")") fi done fi # Handle results if [[ ${#matches[@]} -eq 0 ]]; then # No match found - return the branch name path (will fail later with clear error) echo "$specs_dir/$branch_name" elif [[ ${#matches[@]} -eq 1 ]]; then # Exactly one match - perfect! echo "$specs_dir/${matches[0]}" else # Multiple matches - this shouldn't happen with proper naming convention echo "ERROR: Multiple spec directories found with prefix '$prefix': ${matches[*]}" >&2 echo "Please ensure only one spec directory exists per numeric prefix." >&2 echo "$specs_dir/$branch_name" # Return something to avoid breaking the script fi } get_feature_paths() { local repo_root=$(get_repo_root) local current_branch=$(get_current_branch) local has_git_repo="false" if has_git; then has_git_repo="true" fi # Use prefix-based lookup to support multiple branches per spec local feature_dir=$(find_feature_dir_by_prefix "$repo_root" "$current_branch") cat <<EOF REPO_ROOT='$repo_root' CURRENT_BRANCH='$current_branch' HAS_GIT='$has_git_repo' FEATURE_DIR='$feature_dir' FEATURE_SPEC='$feature_dir/spec.md' IMPL_PLAN='$feature_dir/design.md' TASKS='$feature_dir/tasks.md' RESEARCH='$feature_dir/research.md' DATA_MODEL='$feature_dir/data-model.md' QUICKSTART='$feature_dir/quickstart.md' CONTRACTS_DIR='$feature_dir/contracts' EOF } check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; } check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; } # Color printing utilities print_success() { echo -e "\033[0;32m$1\033[0m"; } print_info() { echo -e "\033[0;36m$1\033[0m"; } print_warning() { echo -e "\033[0;33m$1\033[0m"; } print_error() { echo -e "\033[0;31m$1\033[0m" >&2; } # Detect which AI agent is being used based on directory structure detect_ai_agent() { local repo_root="$1" local agent="unknown" # Check for agent-specific directories in priority order if [[ -d "$repo_root/.claude/commands" ]]; then agent="claude" elif [[ -d "$repo_root/.github/agents" ]]; then agent="copilot" elif [[ -d "$repo_root/.cursor/commands" ]]; then agent="cursor" elif [[ -d "$repo_root/.windsurf/workflows" ]] || [[ -d "$repo_root/.windsurf/rules" ]]; then agent="windsurf" elif [[ -d "$repo_root/.gemini/commands" ]]; then agent="gemini" elif [[ -d "$repo_root/.qwen/commands" ]]; then agent="qwen" elif [[ -d "$repo_root/.opencode/command" ]]; then agent="opencode" elif [[ -d "$repo_root/.codex/commands" ]]; then agent="codex" elif [[ -d "$repo_root/.kilocode/rules" ]]; then agent="kilocode" elif [[ -d "$repo_root/.augment/rules" ]]; then agent="auggie" elif [[ -d "$repo_root/.roo/rules" ]]; then agent="roo" elif [[ -d "$repo_root/.codebuddy/commands" ]]; then agent="codebuddy" elif [[ -d "$repo_root/.amazonq/prompts" ]]; then agent="q" elif [[ -d "$repo_root/.agents/commands" ]]; then agent="amp" elif [[ -d "$repo_root/.shai/commands" ]]; then agent="shai" elif [[ -d "$repo_root/.bob/commands" ]]; then agent="bob" fi echo "$agent" }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DauQuangThanh/sso-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server