Compare commits
No commits in common. "git-scripts" and "master" have entirely different histories.
git-script
...
master
24 changed files with 23 additions and 944 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +0,0 @@
|
||||||
.ots/.attestation-cache
|
|
||||||
|
|
@ -15,72 +15,3 @@ c0685dabfb48360a3abc103b75357f94e9f054b2:pending:1772897691
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772897694
|
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772897694
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772897698
|
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772897698
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772897704
|
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772897704
|
||||||
392ee723c3cf626d0e5281aa94771d7133bb345e:pending:1772897724
|
|
||||||
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:pending:1772897725
|
|
||||||
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:pending:1772897726
|
|
||||||
46aded7b9582bbed673843e2cf8a3f8fa742ad91:pending:1772897727
|
|
||||||
c0685dabfb48360a3abc103b75357f94e9f054b2:pending:1772897728
|
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772897728
|
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772897729
|
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772897730
|
|
||||||
f4eb0ad6782d2bc003206521cc66ea370dcccd9f:pending:1772897732
|
|
||||||
392ee723c3cf626d0e5281aa94771d7133bb345e:pending:1772900099
|
|
||||||
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:pending:1772900100
|
|
||||||
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:pending:1772900100
|
|
||||||
46aded7b9582bbed673843e2cf8a3f8fa742ad91:pending:1772900101
|
|
||||||
c0685dabfb48360a3abc103b75357f94e9f054b2:pending:1772900102
|
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772900103
|
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772900104
|
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772900105
|
|
||||||
f4eb0ad6782d2bc003206521cc66ea370dcccd9f:pending:1772900106
|
|
||||||
4bf5ab21764bc9a4507e25e0bc8de2989d4febad:pending:1772900109
|
|
||||||
392ee723c3cf626d0e5281aa94771d7133bb345e:pending:1772900246
|
|
||||||
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:pending:1772900247
|
|
||||||
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:pending:1772900248
|
|
||||||
46aded7b9582bbed673843e2cf8a3f8fa742ad91:pending:1772900248
|
|
||||||
c0685dabfb48360a3abc103b75357f94e9f054b2:pending:1772900249
|
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772900250
|
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772900251
|
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772900252
|
|
||||||
f4eb0ad6782d2bc003206521cc66ea370dcccd9f:pending:1772900253
|
|
||||||
4bf5ab21764bc9a4507e25e0bc8de2989d4febad:pending:1772900254
|
|
||||||
e2d0ff03529b0a34146dbd97c3ebbb2b2f6d1faa:pending:1772900256
|
|
||||||
392ee723c3cf626d0e5281aa94771d7133bb345e:pending:1772900273
|
|
||||||
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:pending:1772900274
|
|
||||||
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:pending:1772900275
|
|
||||||
46aded7b9582bbed673843e2cf8a3f8fa742ad91:pending:1772900276
|
|
||||||
c0685dabfb48360a3abc103b75357f94e9f054b2:pending:1772900277
|
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772900278
|
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772900279
|
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772900279
|
|
||||||
f4eb0ad6782d2bc003206521cc66ea370dcccd9f:pending:1772900280
|
|
||||||
4bf5ab21764bc9a4507e25e0bc8de2989d4febad:pending:1772900281
|
|
||||||
e2d0ff03529b0a34146dbd97c3ebbb2b2f6d1faa:pending:1772900282
|
|
||||||
a7c0f825be4491ecec199ca7b983ee46525853e5:pending:1772900283
|
|
||||||
392ee723c3cf626d0e5281aa94771d7133bb345e:pending:1772925243
|
|
||||||
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:pending:1772925244
|
|
||||||
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:pending:1772925245
|
|
||||||
46aded7b9582bbed673843e2cf8a3f8fa742ad91:pending:1772925245
|
|
||||||
c0685dabfb48360a3abc103b75357f94e9f054b2:pending:1772925246
|
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772925247
|
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772925248
|
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772925249
|
|
||||||
f4eb0ad6782d2bc003206521cc66ea370dcccd9f:pending:1772925250
|
|
||||||
4bf5ab21764bc9a4507e25e0bc8de2989d4febad:pending:1772925251
|
|
||||||
e2d0ff03529b0a34146dbd97c3ebbb2b2f6d1faa:pending:1772925251
|
|
||||||
a7c0f825be4491ecec199ca7b983ee46525853e5:pending:1772925252
|
|
||||||
02143e59edb79ecf121c99f4518ad232625f5df6:pending:1772925253
|
|
||||||
392ee723c3cf626d0e5281aa94771d7133bb345e:pending:1772926605
|
|
||||||
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:pending:1772926606
|
|
||||||
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:pending:1772926607
|
|
||||||
46aded7b9582bbed673843e2cf8a3f8fa742ad91:pending:1772926608
|
|
||||||
c0685dabfb48360a3abc103b75357f94e9f054b2:pending:1772926608
|
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:pending:1772926609
|
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:pending:1772926610
|
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:pending:1772926611
|
|
||||||
f4eb0ad6782d2bc003206521cc66ea370dcccd9f:pending:1772926612
|
|
||||||
4bf5ab21764bc9a4507e25e0bc8de2989d4febad:pending:1772926613
|
|
||||||
e2d0ff03529b0a34146dbd97c3ebbb2b2f6d1faa:pending:1772926614
|
|
||||||
a7c0f825be4491ecec199ca7b983ee46525853e5:pending:1772926614
|
|
||||||
02143e59edb79ecf121c99f4518ad232625f5df6:pending:1772926615
|
|
||||||
094cd5386431eb9d1fe1335c591452ba0b66cb6e:pending:1772926616
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,9 +1,25 @@
|
||||||
094cd5386431eb9d1fe1335c591452ba0b66cb6e:02143e59edb79ecf121c99f4518ad232625f5df6
|
46aded7b9582bbed673843e2cf8a3f8fa742ad91:4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963
|
||||||
02143e59edb79ecf121c99f4518ad232625f5df6:a7c0f825be4491ecec199ca7b983ee46525853e5
|
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:db6f29e01a33d8ed8f127ff169d9f91d55e8a229
|
||||||
a7c0f825be4491ecec199ca7b983ee46525853e5:e2d0ff03529b0a34146dbd97c3ebbb2b2f6d1faa
|
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:392ee723c3cf626d0e5281aa94771d7133bb345e
|
||||||
e2d0ff03529b0a34146dbd97c3ebbb2b2f6d1faa:4bf5ab21764bc9a4507e25e0bc8de2989d4febad
|
392ee723c3cf626d0e5281aa94771d7133bb345e:392ee723c3cf626d0e5281aa94771d7133bb345e^1
|
||||||
4bf5ab21764bc9a4507e25e0bc8de2989d4febad:f4eb0ad6782d2bc003206521cc66ea370dcccd9f
|
c0685dabfb48360a3abc103b75357f94e9f054b2:46aded7b9582bbed673843e2cf8a3f8fa742ad91
|
||||||
f4eb0ad6782d2bc003206521cc66ea370dcccd9f:ed2cd259e918344c5a21ecf884b3178b4256ea74
|
46aded7b9582bbed673843e2cf8a3f8fa742ad91:4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963
|
||||||
|
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:db6f29e01a33d8ed8f127ff169d9f91d55e8a229
|
||||||
|
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:392ee723c3cf626d0e5281aa94771d7133bb345e
|
||||||
|
392ee723c3cf626d0e5281aa94771d7133bb345e:392ee723c3cf626d0e5281aa94771d7133bb345e^1
|
||||||
|
810d26b7af9c5d306e77fec290d360c7ac876b2e:c0685dabfb48360a3abc103b75357f94e9f054b2
|
||||||
|
c0685dabfb48360a3abc103b75357f94e9f054b2:46aded7b9582bbed673843e2cf8a3f8fa742ad91
|
||||||
|
46aded7b9582bbed673843e2cf8a3f8fa742ad91:4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963
|
||||||
|
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:db6f29e01a33d8ed8f127ff169d9f91d55e8a229
|
||||||
|
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:392ee723c3cf626d0e5281aa94771d7133bb345e
|
||||||
|
392ee723c3cf626d0e5281aa94771d7133bb345e:392ee723c3cf626d0e5281aa94771d7133bb345e^1
|
||||||
|
3b54e0cb8c611d3f3525ad2386368f60200891f1:810d26b7af9c5d306e77fec290d360c7ac876b2e
|
||||||
|
810d26b7af9c5d306e77fec290d360c7ac876b2e:c0685dabfb48360a3abc103b75357f94e9f054b2
|
||||||
|
c0685dabfb48360a3abc103b75357f94e9f054b2:46aded7b9582bbed673843e2cf8a3f8fa742ad91
|
||||||
|
46aded7b9582bbed673843e2cf8a3f8fa742ad91:4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963
|
||||||
|
4a6f5ed0c12315b0bc8a0fa5815ada1bd20e5963:db6f29e01a33d8ed8f127ff169d9f91d55e8a229
|
||||||
|
db6f29e01a33d8ed8f127ff169d9f91d55e8a229:392ee723c3cf626d0e5281aa94771d7133bb345e
|
||||||
|
392ee723c3cf626d0e5281aa94771d7133bb345e:392ee723c3cf626d0e5281aa94771d7133bb345e^1
|
||||||
ed2cd259e918344c5a21ecf884b3178b4256ea74:3b54e0cb8c611d3f3525ad2386368f60200891f1
|
ed2cd259e918344c5a21ecf884b3178b4256ea74:3b54e0cb8c611d3f3525ad2386368f60200891f1
|
||||||
3b54e0cb8c611d3f3525ad2386368f60200891f1:810d26b7af9c5d306e77fec290d360c7ac876b2e
|
3b54e0cb8c611d3f3525ad2386368f60200891f1:810d26b7af9c5d306e77fec290d360c7ac876b2e
|
||||||
810d26b7af9c5d306e77fec290d360c7ac876b2e:c0685dabfb48360a3abc103b75357f94e9f054b2
|
810d26b7af9c5d306e77fec290d360c7ac876b2e:c0685dabfb48360a3abc103b75357f94e9f054b2
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
094cd5386431eb9d1fe1335c591452ba0b66cb6e
|
ed2cd259e918344c5a21ecf884b3178b4256ea74
|
||||||
|
|
|
||||||
BIN
.ots/proof.ots
BIN
.ots/proof.ots
Binary file not shown.
|
|
@ -1,208 +0,0 @@
|
||||||
# Git Hooks Unification Plan
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
Consolidate the current multi-script architecture into standard, self-contained git hook files that can be installed directly without external dependencies.
|
|
||||||
|
|
||||||
## Current Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
scripts/
|
|
||||||
├── generate-proof.sh # Core proof generation logic
|
|
||||||
├── backfill-proofs.sh # History scanning + upgrade
|
|
||||||
├── install-ots-hook.sh # Installer script
|
|
||||||
├── pre-commit-backfill # Pre-commit hook wrapper
|
|
||||||
├── check-attestation.sh # Status checker
|
|
||||||
└── setup-gitignore.sh # Gitignore helper
|
|
||||||
```
|
|
||||||
|
|
||||||
**Problems:**
|
|
||||||
- Hooks depend on external scripts in repo root or global paths
|
|
||||||
- Multiple files to manage and copy
|
|
||||||
- Path resolution logic is fragile
|
|
||||||
- Hard to install manually
|
|
||||||
|
|
||||||
## Target Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
hooks/
|
|
||||||
├── post-commit # Self-contained post-commit hook
|
|
||||||
├── pre-commit # Self-contained pre-commit backfill hook
|
|
||||||
└── install.sh # Simple installer (copies hooks)
|
|
||||||
```
|
|
||||||
|
|
||||||
Each hook file contains all necessary logic inline - no external dependencies.
|
|
||||||
|
|
||||||
## Implementation Plan
|
|
||||||
|
|
||||||
### Phase 1: Create Self-Contained Hooks
|
|
||||||
|
|
||||||
#### `hooks/post-commit`
|
|
||||||
|
|
||||||
Inline the entire `generate-proof.sh` logic:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Self-contained post-commit hook
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
COMMIT_HASH=$(git rev-parse HEAD)
|
|
||||||
OUTPUT_FILE=".ots/proof.ots"
|
|
||||||
mkdir -p "$(dirname "$OUTPUT_FILE")"
|
|
||||||
|
|
||||||
# Inline: generate_with_ots_cli()
|
|
||||||
temp_file=$(mktemp)
|
|
||||||
temp_ots="${temp_file}.ots"
|
|
||||||
python3 -c "import sys; sys.stdout.buffer.write(bytes.fromhex('$COMMIT_HASH'))" > "$temp_file"
|
|
||||||
ots stamp "$temp_file"
|
|
||||||
if [ -f "$temp_ots" ]; then
|
|
||||||
mv "$temp_ots" "$OUTPUT_FILE"
|
|
||||||
rm -f "$temp_file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Inline: get previous commit
|
|
||||||
PREV_COMMIT=$(git rev-parse HEAD^1 2>/dev/null || echo "")
|
|
||||||
if [ -n "$PREV_COMMIT" ]; then
|
|
||||||
echo "$PREV_COMMIT" > ".ots/prev-commit.txt"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[ots] Proof generated: ${COMMIT_HASH:0:8}"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `hooks/pre-commit`
|
|
||||||
|
|
||||||
Inline the entire `backfill-proofs.sh` logic:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Self-contained pre-commit backfill hook
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Inline: cache functions
|
|
||||||
get_cached_status() { ... }
|
|
||||||
cache_status() { ... }
|
|
||||||
|
|
||||||
# Inline: main loop
|
|
||||||
COMMITS=$(git rev-list --reverse HEAD)
|
|
||||||
for COMMIT in $COMMITS; do
|
|
||||||
PROOF_FILE=".ots/${COMMIT}.ots"
|
|
||||||
if [ -f "$PROOF_FILE" ]; then
|
|
||||||
# Check cache, skip if attested
|
|
||||||
# Upgrade if pending and cache expired
|
|
||||||
else
|
|
||||||
# Generate proof inline
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 2: Simplify Installer
|
|
||||||
|
|
||||||
#### `hooks/install.sh`
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Simple installer - just copies hooks
|
|
||||||
|
|
||||||
REPO_PATH="${1:-.}"
|
|
||||||
HOOKS_DIR="$(cd "$REPO_PATH" && git rev-parse --git-dir)/hooks"
|
|
||||||
|
|
||||||
echo "Installing OTS hooks to: $HOOKS_DIR"
|
|
||||||
|
|
||||||
cp "$(dirname "$0")/post-commit" "$HOOKS_DIR/post-commit"
|
|
||||||
cp "$(dirname "$0")/pre-commit" "$HOOKS_DIR/pre-commit"
|
|
||||||
|
|
||||||
chmod +x "$HOOKS_DIR/post-commit" "$HOOKS_DIR/pre-commit"
|
|
||||||
|
|
||||||
echo "✓ Hooks installed"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 3: Migration Path
|
|
||||||
|
|
||||||
1. **Keep current scripts** in `scripts/` for backward compatibility
|
|
||||||
2. **Add new `hooks/`** directory with unified hooks
|
|
||||||
3. **Update SKILL.md** to recommend new hooks
|
|
||||||
4. **Deprecate old scripts** (add deprecation warnings)
|
|
||||||
5. **Eventually remove** old scripts in next major version
|
|
||||||
|
|
||||||
## Benefits
|
|
||||||
|
|
||||||
| Aspect | Before | After |
|
|
||||||
|--------|--------|-------|
|
|
||||||
| Files to install | 6 scripts | 2 hooks + installer |
|
|
||||||
| External dependencies | Yes (scripts in root) | No (self-contained) |
|
|
||||||
| Manual installation | Complex (path resolution) | Simple (copy 2 files) |
|
|
||||||
| Debugging | Hard (multiple files) | Easy (single file per hook) |
|
|
||||||
| Portability | Low (path-dependent) | High (drop-in) |
|
|
||||||
|
|
||||||
## Trade-offs
|
|
||||||
|
|
||||||
**Pros:**
|
|
||||||
- Simpler installation
|
|
||||||
- No path resolution logic
|
|
||||||
- Easier to understand (single file = single responsibility)
|
|
||||||
- Better for manual installation
|
|
||||||
|
|
||||||
**Cons:**
|
|
||||||
- Code duplication (generate-proof logic in both hooks)
|
|
||||||
- Larger hook files (~200-300 lines each)
|
|
||||||
- Harder to update (must update multiple files)
|
|
||||||
|
|
||||||
## Mitigation
|
|
||||||
|
|
||||||
- Extract shared functions into a sourced library: `hooks/.ots-lib.sh`
|
|
||||||
- Hooks source the library: `source "$(dirname "$0")/.ots-lib.sh"`
|
|
||||||
- Library is installed alongside hooks
|
|
||||||
|
|
||||||
## Revised Architecture (with Library)
|
|
||||||
|
|
||||||
```
|
|
||||||
hooks/
|
|
||||||
├── .ots-lib.sh # Shared functions (generate_proof, check_attested, etc.)
|
|
||||||
├── post-commit # Sources library, calls generate_proof()
|
|
||||||
├── pre-commit # Sources library, calls backfill_history()
|
|
||||||
└── install.sh # Copies all files
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
1. [ ] Create `hooks/.ots-lib.sh` with extracted functions
|
|
||||||
2. [ ] Create `hooks/post-commit` using library
|
|
||||||
3. [ ] Create `hooks/pre-commit` using library
|
|
||||||
4. [ ] Create `hooks/install.sh`
|
|
||||||
5. [ ] Test on git-timestamps-test repo
|
|
||||||
6. [ ] Update documentation
|
|
||||||
7. [ ] Deprecate old `scripts/` directory
|
|
||||||
|
|
||||||
## Timeline
|
|
||||||
|
|
||||||
- Phase 1 (Library + Hooks): 1-2 hours
|
|
||||||
- Phase 2 (Testing): 30 min
|
|
||||||
- Phase 3 (Documentation): 30 min
|
|
||||||
- **Total**: ~3 hours
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Branch**: `git-scripts`
|
|
||||||
**Created**: 2026-03-07
|
|
||||||
**Status**: ✅ Complete
|
|
||||||
|
|
||||||
## Implementation Complete
|
|
||||||
|
|
||||||
Created self-contained hooks without shared library:
|
|
||||||
|
|
||||||
```
|
|
||||||
hooks/
|
|
||||||
├── post-commit # 2.8KB - Full proof generation inline
|
|
||||||
├── pre-commit # 4.3KB - Full backfill logic inline
|
|
||||||
└── install.sh # 1.3KB - Simple copier
|
|
||||||
```
|
|
||||||
|
|
||||||
**Test results:**
|
|
||||||
- Commit time: ~14s (11 commits, cached status)
|
|
||||||
- All proofs generated/upgraded correctly
|
|
||||||
- No external script dependencies
|
|
||||||
- Single-file installation
|
|
||||||
|
|
||||||
**Next:** Copy to skill directory and update documentation.
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Git OpenTimestamp Hooks Installer
|
|
||||||
# Detects available tools and installs matching hooks
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
REPO_PATH="${1:-.}"
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
|
|
||||||
cd "$REPO_PATH"
|
|
||||||
|
|
||||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
||||||
echo "Error: not a git repository" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
HOOKS_DIR="$(git rev-parse --git-dir)/hooks"
|
|
||||||
MODE=""
|
|
||||||
|
|
||||||
# Detect available tools
|
|
||||||
if command -v ots &> /dev/null; then
|
|
||||||
MODE="ots"
|
|
||||||
echo "Detected: ots CLI"
|
|
||||||
elif command -v node &> /dev/null && node -e "require('@opentimestamps/ots')" &> /dev/null 2>&1; then
|
|
||||||
MODE="node"
|
|
||||||
echo "Detected: @opentimestamps/ots (Node.js)"
|
|
||||||
echo "Note: Node version creates local proofs only (no calendar submission)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Install node package locally if not already present
|
|
||||||
if [ ! -d "node_modules/@opentimestamps" ]; then
|
|
||||||
echo "Installing @opentimestamps/ots locally..."
|
|
||||||
npm install @opentimestamps/ots
|
|
||||||
echo "✓ Package installed"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Error: Neither ots CLI nor @opentimestamps/ots found" >&2
|
|
||||||
echo "Install one of:" >&2
|
|
||||||
echo " pipx install opentimestamps-client (recommended)" >&2
|
|
||||||
echo " npm install @opentimestamps/ots (local proofs only)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Installing $MODE hooks to: $HOOKS_DIR"
|
|
||||||
|
|
||||||
# Copy appropriate hooks
|
|
||||||
if [ "$MODE" = "ots" ]; then
|
|
||||||
cp "$SCRIPT_DIR/post-commit-ots" "$HOOKS_DIR/post-commit"
|
|
||||||
cp "$SCRIPT_DIR/pre-commit-ots" "$HOOKS_DIR/pre-commit"
|
|
||||||
else
|
|
||||||
cp "$SCRIPT_DIR/post-commit-node" "$HOOKS_DIR/post-commit"
|
|
||||||
cp "$SCRIPT_DIR/pre-commit-node" "$HOOKS_DIR/pre-commit"
|
|
||||||
fi
|
|
||||||
|
|
||||||
chmod +x "$HOOKS_DIR/post-commit" "$HOOKS_DIR/pre-commit"
|
|
||||||
|
|
||||||
echo "✓ Post-commit hook installed"
|
|
||||||
echo "✓ Pre-commit backfill hook installed"
|
|
||||||
|
|
||||||
# Setup .gitignore
|
|
||||||
GITIGNORE=".gitignore"
|
|
||||||
if [ ! -f "$GITIGNORE" ]; then
|
|
||||||
cat > "$GITIGNORE" << 'EOF'
|
|
||||||
.ots/.attestation-cache
|
|
||||||
node_modules/
|
|
||||||
EOF
|
|
||||||
echo "✓ Created .gitignore"
|
|
||||||
elif ! grep -q ".ots/.attestation-cache" "$GITIGNORE"; then
|
|
||||||
echo ".ots/.attestation-cache" >> "$GITIGNORE"
|
|
||||||
if [ "$MODE" = "node" ] && ! grep -q "node_modules/" "$GITIGNORE"; then
|
|
||||||
echo "node_modules/" >> "$GITIGNORE"
|
|
||||||
fi
|
|
||||||
echo "✓ Updated .gitignore"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Mode: $MODE"
|
|
||||||
if [ "$MODE" = "ots" ]; then
|
|
||||||
echo " - Full Bitcoin attestation via calendars"
|
|
||||||
echo " - Proofs submitted to remote calendars"
|
|
||||||
else
|
|
||||||
echo " - Local proofs only (no calendar submission)"
|
|
||||||
echo " - For full attestation, use: pipx install opentimestamps-client"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Next steps:"
|
|
||||||
echo "1. Make a test commit"
|
|
||||||
echo "2. Commit proofs: git add .ots/ && git commit -m 'Add OpenTimestamp proofs'"
|
|
||||||
echo ""
|
|
||||||
echo "To uninstall:"
|
|
||||||
echo " rm $HOOKS_DIR/post-commit $HOOKS_DIR/pre-commit"
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
#!/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"
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Git OpenTimestamp Post-Commit Hook (Node.js version)
|
|
||||||
# Requires: @opentimestamps/ots (npm install)
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
OUTPUT_DIR=".ots"
|
|
||||||
OUTPUT_FILE="$OUTPUT_DIR/proof.ots"
|
|
||||||
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
COMMIT_HASH=$(git rev-parse HEAD)
|
|
||||||
|
|
||||||
# Generate proof using Node.js
|
|
||||||
node -e "
|
|
||||||
const ots = require('@opentimestamps/ots');
|
|
||||||
const fs = require('fs');
|
|
||||||
const hash = '$COMMIT_HASH';
|
|
||||||
const output = '$OUTPUT_FILE';
|
|
||||||
const hashBuffer = Buffer.from(hash, 'hex');
|
|
||||||
|
|
||||||
ots.Timestamp.hash(hashBuffer).then(timestamp => {
|
|
||||||
// Note: This creates a local proof only, not submitted to calendars
|
|
||||||
// For full Bitcoin attestation, use the ots CLI version
|
|
||||||
const proof = {
|
|
||||||
hash: hash,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
status: 'pending',
|
|
||||||
note: 'Local proof only - use ots CLI for calendar submission'
|
|
||||||
};
|
|
||||||
fs.writeFileSync(output, JSON.stringify(proof, null, 2));
|
|
||||||
console.log('[ots-node] Generated local proof: ' + hash.substring(0, 8));
|
|
||||||
}).catch(err => {
|
|
||||||
console.error('[ots-node] Error:', err.message);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
"
|
|
||||||
|
|
||||||
# Save previous commit 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 (JSON format for node version)
|
|
||||||
INDIVIDUAL_PROOF="$OUTPUT_DIR/${COMMIT_HASH}.ots"
|
|
||||||
cp "$OUTPUT_FILE" "$INDIVIDUAL_PROOF"
|
|
||||||
|
|
||||||
echo "[ots-node] Proof generated successfully"
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Git OpenTimestamp Post-Commit Hook (ots CLI version)
|
|
||||||
# Requires: opentimestamps-client (pipx install opentimestamps-client)
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
OUTPUT_DIR=".ots"
|
|
||||||
OUTPUT_FILE="$OUTPUT_DIR/proof.ots"
|
|
||||||
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
COMMIT_HASH=$(git rev-parse HEAD)
|
|
||||||
|
|
||||||
# Generate proof using ots CLI
|
|
||||||
temp_file=$(mktemp)
|
|
||||||
temp_ots="${temp_file}.ots"
|
|
||||||
|
|
||||||
python3 -c "import sys; sys.stdout.buffer.write(bytes.fromhex('$COMMIT_HASH'))" > "$temp_file"
|
|
||||||
ots stamp "$temp_file" 2>/dev/null
|
|
||||||
|
|
||||||
if [ -f "$temp_ots" ]; then
|
|
||||||
mv "$temp_ots" "$OUTPUT_FILE"
|
|
||||||
rm -f "$temp_file"
|
|
||||||
echo "[ots] Generated proof: ${COMMIT_HASH:0:8}"
|
|
||||||
else
|
|
||||||
rm -f "$temp_file"
|
|
||||||
echo "[ots] Warning: Failed to generate proof" >&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Save previous commit 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
|
|
||||||
INDIVIDUAL_PROOF="$OUTPUT_DIR/${COMMIT_HASH}.ots"
|
|
||||||
cp "$OUTPUT_FILE" "$INDIVIDUAL_PROOF"
|
|
||||||
|
|
||||||
echo "[ots] Proof generated successfully"
|
|
||||||
156
hooks/pre-commit
156
hooks/pre-commit
|
|
@ -1,156 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Git OpenTimestamp Pre-Commit Backfill Hook
|
|
||||||
# Self-contained - no external dependencies
|
|
||||||
# Upgrades all historical proofs before each new commit
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
OUTPUT_DIR=".ots"
|
|
||||||
STATUS_CACHE="$OUTPUT_DIR/.attestation-cache"
|
|
||||||
|
|
||||||
# Ensure output directory exists
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
# Initialize cache file if it doesn't exist
|
|
||||||
if [ ! -f "$STATUS_CACHE" ]; then
|
|
||||||
echo "# Attestation status cache" > "$STATUS_CACHE"
|
|
||||||
echo "# Format: commit-hash:status:timestamp" >> "$STATUS_CACHE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Function to get cached status
|
|
||||||
get_cached_status() {
|
|
||||||
local commit="$1"
|
|
||||||
local cache_line=$(grep "^$commit:" "$STATUS_CACHE" 2>/dev/null | tail -1)
|
|
||||||
if [ -n "$cache_line" ]; then
|
|
||||||
local status=$(echo "$cache_line" | cut -d: -f2)
|
|
||||||
local timestamp=$(echo "$cache_line" | cut -d: -f3)
|
|
||||||
local now=$(date +%s)
|
|
||||||
local age=$((now - timestamp))
|
|
||||||
# Cache valid for 1 hour (3600 seconds)
|
|
||||||
if [ "$age" -lt 3600 ]; then
|
|
||||||
echo "$status"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to cache status
|
|
||||||
cache_status() {
|
|
||||||
local commit="$1"
|
|
||||||
local status="$2"
|
|
||||||
local now=$(date +%s)
|
|
||||||
echo "$commit:$status:$now" >> "$STATUS_CACHE"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to generate proof using ots CLI
|
|
||||||
generate_proof() {
|
|
||||||
local hash="$1"
|
|
||||||
local output="$2"
|
|
||||||
|
|
||||||
local temp_file=$(mktemp)
|
|
||||||
local temp_ots="${temp_file}.ots"
|
|
||||||
|
|
||||||
python3 -c "import sys; sys.stdout.buffer.write(bytes.fromhex('$hash'))" > "$temp_file"
|
|
||||||
ots stamp "$temp_file" 2>/dev/null
|
|
||||||
|
|
||||||
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 check if proof is attested
|
|
||||||
is_attested() {
|
|
||||||
local proof_file="$1"
|
|
||||||
local pending_count=$(ots info "$proof_file" 2>&1 | grep -c "PendingAttestation" || echo "0")
|
|
||||||
[ "$pending_count" -eq 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to upgrade proof
|
|
||||||
upgrade_proof() {
|
|
||||||
local proof_file="$1"
|
|
||||||
ots upgrade "$proof_file" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "[ots] Backfilling proofs..."
|
|
||||||
|
|
||||||
# Get all commit hashes (oldest to newest)
|
|
||||||
COMMITS=$(git rev-list --reverse HEAD)
|
|
||||||
TOTAL=$(echo "$COMMITS" | wc -l)
|
|
||||||
CURRENT=0
|
|
||||||
UPDATED=0
|
|
||||||
|
|
||||||
for COMMIT in $COMMITS; do
|
|
||||||
CURRENT=$((CURRENT + 1))
|
|
||||||
PROOF_FILE="$OUTPUT_DIR/${COMMIT}.ots"
|
|
||||||
|
|
||||||
# Skip verbose output for brevity
|
|
||||||
if [ $CURRENT -le 3 ] || [ $CURRENT -eq $TOTAL ]; then
|
|
||||||
echo "[ots] Processing commit $CURRENT/$TOTAL: ${COMMIT:0:8}"
|
|
||||||
elif [ $CURRENT -eq 4 ]; then
|
|
||||||
echo "[ots] ... processing remaining commits ..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$PROOF_FILE" ]; then
|
|
||||||
# Check cached status first
|
|
||||||
CACHED_STATUS=$(get_cached_status "$COMMIT" || echo "")
|
|
||||||
|
|
||||||
if [ "$CACHED_STATUS" = "attested" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if already attested
|
|
||||||
if is_attested "$PROOF_FILE"; then
|
|
||||||
cache_status "$COMMIT" "attested"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Cache as pending
|
|
||||||
cache_status "$COMMIT" "pending"
|
|
||||||
|
|
||||||
# Skip upgrade if cache is fresh (< 10 min old)
|
|
||||||
CACHE_LINE=$(grep "^$COMMIT:" "$STATUS_CACHE" | tail -1)
|
|
||||||
CACHE_TIME=$(echo "$CACHE_LINE" | cut -d: -f3)
|
|
||||||
NOW=$(date +%s)
|
|
||||||
CACHE_AGE=$((NOW - CACHE_TIME))
|
|
||||||
|
|
||||||
if [ "$CACHE_AGE" -lt 600 ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try to upgrade
|
|
||||||
if upgrade_proof "$PROOF_FILE"; then
|
|
||||||
cache_status "$COMMIT" "attested"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Generate new proof
|
|
||||||
if generate_proof "$COMMIT" "$PROOF_FILE"; then
|
|
||||||
cache_status "$COMMIT" "pending"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Update latest proof symlink
|
|
||||||
LATEST_COMMIT=$(git rev-parse HEAD)
|
|
||||||
if [ -f "$OUTPUT_DIR/${LATEST_COMMIT}.ots" ]; then
|
|
||||||
cp "$OUTPUT_DIR/${LATEST_COMMIT}.ots" "$OUTPUT_DIR/proof.ots"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Save commit chain
|
|
||||||
rm -f "$OUTPUT_DIR/commit-chain.txt"
|
|
||||||
git rev-list HEAD | while read COMMIT; do
|
|
||||||
PREV=$(git rev-parse ${COMMIT}^1 2>/dev/null || echo "")
|
|
||||||
if [ -n "$PREV" ]; then
|
|
||||||
echo "$COMMIT:$PREV" >> "$OUTPUT_DIR/commit-chain.txt"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "[ots] Backfill complete: $UPDATED proofs updated"
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Git OpenTimestamp Pre-Commit Backfill Hook (Node.js version)
|
|
||||||
# Requires: @opentimestamps/ots (npm install)
|
|
||||||
# Note: Node version only generates local proofs, no calendar submission
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
OUTPUT_DIR=".ots"
|
|
||||||
STATUS_CACHE="$OUTPUT_DIR/.attestation-cache"
|
|
||||||
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
# Initialize cache
|
|
||||||
if [ ! -f "$STATUS_CACHE" ]; then
|
|
||||||
echo "# Format: commit-hash:status:timestamp" > "$STATUS_CACHE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
get_cached_status() {
|
|
||||||
local commit="$1"
|
|
||||||
local cache_line=$(grep "^$commit:" "$STATUS_CACHE" 2>/dev/null | tail -1)
|
|
||||||
if [ -n "$cache_line" ]; then
|
|
||||||
local status=$(echo "$cache_line" | cut -d: -f2)
|
|
||||||
local timestamp=$(echo "$cache_line" | cut -d: -f3)
|
|
||||||
local now=$(date +%s)
|
|
||||||
if [ "$((now - timestamp))" -lt 3600 ]; then
|
|
||||||
echo "$status"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_status() {
|
|
||||||
local commit="$1"
|
|
||||||
local status="$2"
|
|
||||||
echo "$commit:$status:$(date +%s)" >> "$STATUS_CACHE"
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_proof_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));
|
|
||||||
}).catch(err => { console.error('Error:', err); process.exit(1); });
|
|
||||||
"
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "[ots-node] Backfilling proofs (local only, no calendar)..."
|
|
||||||
|
|
||||||
COMMITS=$(git rev-list --reverse HEAD)
|
|
||||||
TOTAL=$(echo "$COMMITS" | wc -l)
|
|
||||||
CURRENT=0
|
|
||||||
UPDATED=0
|
|
||||||
|
|
||||||
for COMMIT in $COMMITS; do
|
|
||||||
CURRENT=$((CURRENT + 1))
|
|
||||||
PROOF_FILE="$OUTPUT_DIR/${COMMIT}.ots"
|
|
||||||
|
|
||||||
if [ $CURRENT -le 3 ] || [ $CURRENT -eq $TOTAL ]; then
|
|
||||||
echo "[ots-node] Processing $CURRENT/$TOTAL: ${COMMIT:0:8}"
|
|
||||||
elif [ $CURRENT -eq 4 ]; then
|
|
||||||
echo "[ots-node] ... processing remaining ..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$PROOF_FILE" ]; then
|
|
||||||
# Node version doesn't support upgrade, just check cache
|
|
||||||
CACHED_STATUS=$(get_cached_status "$COMMIT" || echo "")
|
|
||||||
[ "$CACHED_STATUS" = "attested" ] && continue
|
|
||||||
|
|
||||||
# Mark as pending (node can't attest)
|
|
||||||
cache_status "$COMMIT" "pending"
|
|
||||||
else
|
|
||||||
if generate_proof_node "$COMMIT" "$PROOF_FILE"; then
|
|
||||||
cache_status "$COMMIT" "pending"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Update latest proof
|
|
||||||
LATEST_COMMIT=$(git rev-parse HEAD)
|
|
||||||
[ -f "$OUTPUT_DIR/${LATEST_COMMIT}.ots" ] && cp "$OUTPUT_DIR/${LATEST_COMMIT}.ots" "$OUTPUT_DIR/proof.ots"
|
|
||||||
|
|
||||||
# Save commit chain
|
|
||||||
rm -f "$OUTPUT_DIR/commit-chain.txt"
|
|
||||||
git rev-list HEAD | while read COMMIT; do
|
|
||||||
PREV=$(git rev-parse ${COMMIT}^1 2>/dev/null || echo "")
|
|
||||||
[ -n "$PREV" ] && echo "$COMMIT:$PREV" >> "$OUTPUT_DIR/commit-chain.txt"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "[ots-node] Backfill complete: $UPDATED generated (local proofs only)"
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Git OpenTimestamp Pre-Commit Backfill Hook (ots CLI version)
|
|
||||||
# Requires: opentimestamps-client (pipx install opentimestamps-client)
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
OUTPUT_DIR=".ots"
|
|
||||||
STATUS_CACHE="$OUTPUT_DIR/.attestation-cache"
|
|
||||||
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
# Initialize cache
|
|
||||||
if [ ! -f "$STATUS_CACHE" ]; then
|
|
||||||
echo "# Format: commit-hash:status:timestamp" > "$STATUS_CACHE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
get_cached_status() {
|
|
||||||
local commit="$1"
|
|
||||||
local cache_line=$(grep "^$commit:" "$STATUS_CACHE" 2>/dev/null | tail -1)
|
|
||||||
if [ -n "$cache_line" ]; then
|
|
||||||
local status=$(echo "$cache_line" | cut -d: -f2)
|
|
||||||
local timestamp=$(echo "$cache_line" | cut -d: -f3)
|
|
||||||
local now=$(date +%s)
|
|
||||||
if [ "$((now - timestamp))" -lt 3600 ]; then
|
|
||||||
echo "$status"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_status() {
|
|
||||||
local commit="$1"
|
|
||||||
local status="$2"
|
|
||||||
echo "$commit:$status:$(date +%s)" >> "$STATUS_CACHE"
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_proof() {
|
|
||||||
local hash="$1"
|
|
||||||
local output="$2"
|
|
||||||
local temp_file=$(mktemp)
|
|
||||||
local temp_ots="${temp_file}.ots"
|
|
||||||
|
|
||||||
python3 -c "import sys; sys.stdout.buffer.write(bytes.fromhex('$hash'))" > "$temp_file"
|
|
||||||
ots stamp "$temp_file" 2>/dev/null
|
|
||||||
|
|
||||||
if [ -f "$temp_ots" ]; then
|
|
||||||
mv "$temp_ots" "$output"
|
|
||||||
rm -f "$temp_file"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
rm -f "$temp_file"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
is_attested() {
|
|
||||||
local proof_file="$1"
|
|
||||||
local pending_count=$(ots info "$proof_file" 2>&1 | grep -c "PendingAttestation" || echo "0")
|
|
||||||
[ "$pending_count" -eq 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
upgrade_proof() {
|
|
||||||
local proof_file="$1"
|
|
||||||
ots upgrade "$proof_file" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "[ots] Backfilling proofs..."
|
|
||||||
|
|
||||||
COMMITS=$(git rev-list --reverse HEAD)
|
|
||||||
TOTAL=$(echo "$COMMITS" | wc -l)
|
|
||||||
CURRENT=0
|
|
||||||
UPDATED=0
|
|
||||||
|
|
||||||
for COMMIT in $COMMITS; do
|
|
||||||
CURRENT=$((CURRENT + 1))
|
|
||||||
PROOF_FILE="$OUTPUT_DIR/${COMMIT}.ots"
|
|
||||||
|
|
||||||
if [ $CURRENT -le 3 ] || [ $CURRENT -eq $TOTAL ]; then
|
|
||||||
echo "[ots] Processing $CURRENT/$TOTAL: ${COMMIT:0:8}"
|
|
||||||
elif [ $CURRENT -eq 4 ]; then
|
|
||||||
echo "[ots] ... processing remaining ..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$PROOF_FILE" ]; then
|
|
||||||
CACHED_STATUS=$(get_cached_status "$COMMIT" || echo "")
|
|
||||||
|
|
||||||
[ "$CACHED_STATUS" = "attested" ] && continue
|
|
||||||
|
|
||||||
if is_attested "$PROOF_FILE"; then
|
|
||||||
cache_status "$COMMIT" "attested"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
cache_status "$COMMIT" "pending"
|
|
||||||
|
|
||||||
CACHE_LINE=$(grep "^$COMMIT:" "$STATUS_CACHE" | tail -1)
|
|
||||||
CACHE_TIME=$(echo "$CACHE_LINE" | cut -d: -f3)
|
|
||||||
CACHE_AGE=$(($(date +%s) - CACHE_TIME))
|
|
||||||
|
|
||||||
[ "$CACHE_AGE" -lt 600 ] && continue
|
|
||||||
|
|
||||||
if upgrade_proof "$PROOF_FILE"; then
|
|
||||||
cache_status "$COMMIT" "attested"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if generate_proof "$COMMIT" "$PROOF_FILE"; then
|
|
||||||
cache_status "$COMMIT" "pending"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Update latest proof
|
|
||||||
LATEST_COMMIT=$(git rev-parse HEAD)
|
|
||||||
[ -f "$OUTPUT_DIR/${LATEST_COMMIT}.ots" ] && cp "$OUTPUT_DIR/${LATEST_COMMIT}.ots" "$OUTPUT_DIR/proof.ots"
|
|
||||||
|
|
||||||
# Save commit chain
|
|
||||||
rm -f "$OUTPUT_DIR/commit-chain.txt"
|
|
||||||
git rev-list HEAD | while read COMMIT; do
|
|
||||||
PREV=$(git rev-parse ${COMMIT}^1 2>/dev/null || echo "")
|
|
||||||
[ -n "$PREV" ] && echo "$COMMIT:$PREV" >> "$OUTPUT_DIR/commit-chain.txt"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "[ots] Backfill complete: $UPDATED updated"
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# Another test commit
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# Test new ots-only hooks
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# Test renamed hooks
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# Test self-contained hooks
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue