git-timestamps/hooks/post-commit
2026-03-07 17:17:25 +01:00

91 lines
2.8 KiB
Bash
Executable file

#!/bin/bash
# Git OpenTimestamp Post-Commit Hook
# Self-contained - no external dependencies
# Generates cryptographic proof for each commit using OpenTimestamp
set -e
# Configuration
OUTPUT_DIR=".ots"
OUTPUT_FILE="$OUTPUT_DIR/proof.ots"
# Ensure output directory exists
mkdir -p "$OUTPUT_DIR"
# Get the current commit hash
COMMIT_HASH=$(git rev-parse HEAD)
# Function to generate proof using ots CLI
generate_with_ots_cli() {
local hash="$1"
local output="$2"
# Create a temporary file with the hash (convert hex to binary)
local temp_file=$(mktemp)
local temp_ots="${temp_file}.ots"
# Use python3 for hex to binary conversion (more portable than xxd)
python3 -c "import sys; sys.stdout.buffer.write(bytes.fromhex('$hash'))" > "$temp_file"
# Generate timestamp - ots creates .ots file alongside the original
ots stamp "$temp_file" 2>/dev/null
# Move the generated .ots file to the desired location
if [ -f "$temp_ots" ]; then
mv "$temp_ots" "$output"
rm -f "$temp_file"
return 0
else
rm -f "$temp_file"
return 1
fi
}
# Function to generate proof using nodejs fallback
generate_with_node() {
local hash="$1"
local output="$2"
node -e "
const ots = require('@opentimestamps/ots');
const fs = require('fs');
const hash = '$hash';
const output = '$output';
const hashBuffer = Buffer.from(hash, 'hex');
ots.Timestamp.hash(hashBuffer).then(timestamp => {
const proof = { hash: hash, timestamp: new Date().toISOString(), status: 'pending' };
fs.writeFileSync(output, JSON.stringify(proof, null, 2));
console.log('Generated local proof (nodejs fallback)');
}).catch(err => { console.error('Error:', err); process.exit(1); });
"
}
# Check for available tools and generate proof
if command -v ots &> /dev/null; then
if generate_with_ots_cli "$COMMIT_HASH" "$OUTPUT_FILE"; then
echo "[ots] Generated proof with ots CLI: ${COMMIT_HASH:0:8}"
else
echo "[ots] Warning: ots CLI failed" >&2
exit 0
fi
elif command -v node &> /dev/null && node -e "require('@opentimestamps/ots')" &> /dev/null 2>&1; then
generate_with_node "$COMMIT_HASH" "$OUTPUT_FILE"
echo "[ots] Generated proof with nodejs fallback: ${COMMIT_HASH:0:8}"
else
echo "[ots] Warning: Neither ots CLI nor @opentimestamps/ots found, skipping proof" >&2
exit 0
fi
# Save previous commit hash for chaining
PREV_COMMIT=$(git rev-parse HEAD^1 2>/dev/null || echo "")
if [ -n "$PREV_COMMIT" ]; then
echo "$PREV_COMMIT" > "$OUTPUT_DIR/prev-commit.txt"
fi
# Create individual proof file for this commit
INDIVIDUAL_PROOF="$OUTPUT_DIR/${COMMIT_HASH}.ots"
if [ -f "$OUTPUT_FILE" ]; then
cp "$OUTPUT_FILE" "$INDIVIDUAL_PROOF"
fi
echo "[ots] Proof generated successfully"