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>
36 lines
863 B
Go
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
|
|
}
|