Files
beads/internal/storage/sqlite/hash.go
Steve Yegge a898df6915 WIP: bd-164 timestamp-only export deduplication (~80% complete)
Implemented content hash-based deduplication to skip exports when only
timestamps changed. Core logic complete, needs export_hashes table wiring.

Completed:
- Added computeIssueContentHash() excluding timestamps
- Created shouldSkipExport() logic
- Updated export loop to skip timestamp-only changes
- Added hash.go with content hashing
- Extended Storage interface

Remaining:
- Complete export_hashes table migration
- Add SetExportHash/GetExportHash to interface
- Revert content_hash from dirty_issues approach
- Wire up hash persistence in export
- Testing

See bd-164 notes for details.

Amp-Thread-ID: https://ampcode.com/threads/T-d70657d1-4433-4f7e-b10a-3fccf8bf17fb
Co-authored-by: Amp <amp@ampcode.com>
2025-10-26 20:29:10 -07:00

36 lines
863 B
Go

package sqlite
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"time"
"github.com/steveyegge/beads/internal/types"
)
// computeIssueContentHash computes a SHA256 hash of an issue's content, excluding timestamps.
// This is used for detecting timestamp-only changes during export deduplication.
func computeIssueContentHash(issue *types.Issue) (string, error) {
// Clone issue and zero out timestamps to exclude them from hash
normalized := *issue
normalized.CreatedAt = time.Time{}
normalized.UpdatedAt = time.Time{}
// Also zero out ClosedAt if present
if normalized.ClosedAt != nil {
zeroTime := time.Time{}
normalized.ClosedAt = &zeroTime
}
// Serialize to JSON
data, err := json.Marshal(normalized)
if err != nil {
return "", err
}
// SHA256 hash
hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:]), nil
}