91 lines
2.8 KiB
Bash
Executable file
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"
|