aboutsummaryrefslogtreecommitdiff
path: root/validators/bash
diff options
context:
space:
mode:
authorAlex Pooley (@zuedev) <zuedev@gmail.com>2026-02-05 16:03:08 +0000
committerAlex Pooley (@zuedev) <zuedev@gmail.com>2026-02-05 16:03:08 +0000
commit4775de64eb752b90267114c0c1c95235820521f3 (patch)
treea24d73dd2ebe337a45bb6347c7be856bf72afad4 /validators/bash
parent6857b2514ac26a0731208e6f7c312cd70b606544 (diff)
downloadgitinfo-4775de64eb752b90267114c0c1c95235820521f3.tar
gitinfo-4775de64eb752b90267114c0c1c95235820521f3.tar.gz
gitinfo-4775de64eb752b90267114c0c1c95235820521f3.tar.bz2
gitinfo-4775de64eb752b90267114c0c1c95235820521f3.tar.xz
gitinfo-4775de64eb752b90267114c0c1c95235820521f3.zip
add CLI validators in Node.js, PowerShell, and Bash
Move validate.js to validators/nodejs/ and add equivalent validators for PowerShell and Bash. Each includes a README with usage instructions and requirements.
Diffstat (limited to 'validators/bash')
-rw-r--r--validators/bash/README.md60
-rw-r--r--validators/bash/validate.sh172
2 files changed, 232 insertions, 0 deletions
diff --git a/validators/bash/README.md b/validators/bash/README.md
new file mode 100644
index 0000000..3692a1d
--- /dev/null
+++ b/validators/bash/README.md
@@ -0,0 +1,60 @@
+# Bash Validator
+
+A Bash script for validating `.gitinfo` files.
+
+## Requirements
+
+- Bash 4+
+- [jq](https://jqlang.github.io/jq/) (JSON processor)
+
+Install jq:
+
+```bash
+# Debian/Ubuntu
+apt install jq
+
+# macOS
+brew install jq
+
+# Windows (via Chocolatey)
+choco install jq
+```
+
+## Usage
+
+```bash
+# Make executable (first time only)
+chmod +x validate.sh
+
+# Validate .gitinfo in current directory
+./validate.sh
+
+# Validate a specific file
+./validate.sh path/to/.gitinfo
+```
+
+## Features
+
+- Parses JSONC (strips `//` and `/* */` comments)
+- Validates against the gitinfo JSON Schema
+- Checks types and formats (URI, email)
+- Enforces `additionalProperties: false`
+- Returns exit code 0 on success, 1 on failure
+- Color-coded output (green for success, red for errors)
+
+## Example Output
+
+```
+✓ .gitinfo is valid
+```
+
+```
+Validation failed for .gitinfo:
+ - .root: invalid URI "not-a-url"
+ - root: unknown property "invalid_field"
+```
+
+## Limitations
+
+- Comment stripping is simplified and may not handle edge cases with comments inside strings
+- For complex validation, consider using the Node.js validator
diff --git a/validators/bash/validate.sh b/validators/bash/validate.sh
new file mode 100644
index 0000000..55324f1
--- /dev/null
+++ b/validators/bash/validate.sh
@@ -0,0 +1,172 @@
+#!/usr/bin/env bash
+
+# CLI validator for .gitinfo files
+# Usage: ./validate.sh [file]
+# ./validate.sh # validates .gitinfo in current directory
+# ./validate.sh path/to/.gitinfo
+
+set -e
+
+# Schema path (two levels up from validators/bash/)
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+SCHEMA_PATH="$SCRIPT_DIR/../../gitinfo.schema.json"
+
+# Colors
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+NC='\033[0m' # No Color
+
+# Check for jq
+if ! command -v jq &> /dev/null; then
+ echo -e "${RED}Error: jq is required but not installed.${NC}" >&2
+ echo "Install with: apt install jq / brew install jq / choco install jq" >&2
+ exit 1
+fi
+
+# Strip JSONC comments using sed
+strip_comments() {
+ # Remove single-line comments (// ...) and multi-line comments (/* ... */)
+ # This is a simplified version - doesn't handle comments inside strings perfectly
+ sed -e 's|//.*$||g' -e ':a;s|/\*.*\*/||g;ta' -e '/\/\*/,/\*\//d' "$1"
+}
+
+# Validate URI format
+validate_uri() {
+ local uri="$1"
+ if [[ "$uri" =~ ^https?:// ]]; then
+ return 0
+ fi
+ return 1
+}
+
+# Validate email format
+validate_email() {
+ local email="$1"
+ if [[ "$email" =~ ^[^[:space:]@]+@[^[:space:]@]+\.[^[:space:]@]+$ ]]; then
+ return 0
+ fi
+ return 1
+}
+
+# Main validation function
+validate() {
+ local file="$1"
+ local errors=()
+
+ # Parse JSON
+ local json
+ if ! json=$(strip_comments "$file" | jq -c . 2>&1); then
+ echo -e "${RED}Error parsing JSONC: $json${NC}" >&2
+ exit 1
+ fi
+
+ # Load schema
+ local schema
+ if ! schema=$(jq -c . "$SCHEMA_PATH" 2>&1); then
+ echo -e "${RED}Error parsing schema: $schema${NC}" >&2
+ exit 1
+ fi
+
+ # Check if root is an object
+ local type
+ type=$(echo "$json" | jq -r 'type')
+ if [[ "$type" != "object" ]]; then
+ errors+=("root: expected object, got $type")
+ fi
+
+ # Get allowed properties from schema
+ local allowed_props
+ allowed_props=$(echo "$schema" | jq -r '.properties | keys[]')
+
+ # Check for unknown properties
+ local actual_props
+ actual_props=$(echo "$json" | jq -r 'keys[]')
+ for prop in $actual_props; do
+ if ! echo "$allowed_props" | grep -qx "$prop"; then
+ errors+=("root: unknown property \"$prop\"")
+ fi
+ done
+
+ # Validate each property
+ local schema_props
+ schema_props=$(echo "$schema" | jq -r '.properties | to_entries[] | @base64')
+
+ for entry in $schema_props; do
+ local key format prop_type
+ key=$(echo "$entry" | base64 -d | jq -r '.key')
+ format=$(echo "$entry" | base64 -d | jq -r '.value.format // empty')
+ prop_type=$(echo "$entry" | base64 -d | jq -r '.value.type')
+
+ # Check if property exists
+ local value
+ value=$(echo "$json" | jq -r --arg k "$key" '.[$k] // empty')
+
+ if [[ -n "$value" && "$value" != "null" ]]; then
+ local actual_type
+ actual_type=$(echo "$json" | jq -r --arg k "$key" '.[$k] | type')
+
+ # Type check
+ if [[ "$prop_type" == "string" && "$actual_type" != "string" ]]; then
+ errors+=(".$key: expected string")
+ elif [[ "$prop_type" == "array" && "$actual_type" != "array" ]]; then
+ errors+=(".$key: expected array")
+ fi
+
+ # Format validation for strings
+ if [[ "$actual_type" == "string" ]]; then
+ if [[ "$format" == "uri" ]]; then
+ if ! validate_uri "$value"; then
+ errors+=(".$key: invalid URI \"$value\"")
+ fi
+ elif [[ "$format" == "email" ]]; then
+ if ! validate_email "$value"; then
+ errors+=(".$key: invalid email \"$value\"")
+ fi
+ fi
+ fi
+
+ # Validate array items
+ if [[ "$actual_type" == "array" ]]; then
+ local item_format
+ item_format=$(echo "$entry" | base64 -d | jq -r '.value.items.format // empty')
+
+ if [[ "$item_format" == "uri" ]]; then
+ local i=0
+ while IFS= read -r item; do
+ if ! validate_uri "$item"; then
+ errors+=(".${key}[$i]: invalid URI \"$item\"")
+ fi
+ ((i++))
+ done < <(echo "$json" | jq -r --arg k "$key" '.[$k][]?')
+ fi
+ fi
+ fi
+ done
+
+ # Output results
+ if [[ ${#errors[@]} -gt 0 ]]; then
+ echo -e "${RED}Validation failed for $file:${NC}" >&2
+ for error in "${errors[@]}"; do
+ echo -e " - $error" >&2
+ done
+ exit 1
+ fi
+
+ echo -e "${GREEN}✓ $file is valid${NC}"
+ exit 0
+}
+
+# Main
+FILE="${1:-.gitinfo}"
+
+if [[ ! -f "$FILE" ]]; then
+ echo -e "${RED}Error: File not found: $FILE${NC}" >&2
+ exit 1
+fi
+
+if [[ ! -f "$SCHEMA_PATH" ]]; then
+ echo -e "${RED}Error: Schema not found: $SCHEMA_PATH${NC}" >&2
+ exit 1
+fi
+
+validate "$FILE"