entity: unique function to generate IDs

Michael Muré created

Change summary

bug/operation.go    | 10 ++--------
entity/id.go        | 14 ++++++++++++++
identity/version.go | 12 +++---------
3 files changed, 19 insertions(+), 17 deletions(-)

Detailed changes

bug/operation.go 🔗

@@ -1,7 +1,6 @@
 package bug
 
 import (
-	"crypto/sha256"
 	"encoding/json"
 	"fmt"
 	"time"
@@ -55,11 +54,6 @@ type Operation interface {
 	IsOperation()
 }
 
-func deriveId(data []byte) entity.Id {
-	sum := sha256.Sum256(data)
-	return entity.Id(fmt.Sprintf("%x", sum))
-}
-
 func idOperation(op Operation) entity.Id {
 	base := op.base()
 
@@ -78,7 +72,7 @@ func idOperation(op Operation) entity.Id {
 			panic(err)
 		}
 
-		base.id = deriveId(data)
+		base.id = entity.DeriveId(data)
 	}
 	return base.id
 }
@@ -109,7 +103,7 @@ func newOpBase(opType OperationType, author identity.Interface, unixTime int64)
 
 func (op *OpBase) UnmarshalJSON(data []byte) error {
 	// Compute the Id when loading the op from disk.
-	op.id = deriveId(data)
+	op.id = entity.DeriveId(data)
 
 	aux := struct {
 		OperationType OperationType     `json:"type"`

entity/id.go 🔗

@@ -1,6 +1,7 @@
 package entity
 
 import (
+	"crypto/sha256"
 	"fmt"
 	"io"
 	"strings"
@@ -17,6 +18,15 @@ const UnsetId = Id("unset")
 // Id is an identifier for an entity or part of an entity
 type Id string
 
+// DeriveId generate an Id from some data, taken from a root part of the entity.
+func DeriveId(data []byte) Id {
+	// My understanding is that sha256 is enough to prevent collision (git use that, so ...?)
+	// If you read this code, I'd be happy to be schooled.
+
+	sum := sha256.Sum256(data)
+	return Id(fmt.Sprintf("%x", sum))
+}
+
 // String return the identifier as a string
 func (i Id) String() string {
 	return string(i)
@@ -55,6 +65,10 @@ func (i Id) MarshalGQL(w io.Writer) {
 
 // IsValid tell if the Id is valid
 func (i Id) Validate() error {
+	// Special case to
+	if len(i) == 40 {
+		return fmt.Errorf("outdated repository format, please use https://github.com/MichaelMure/git-bug-migration to upgrade")
+	}
 	if len(i) != idLength {
 		return fmt.Errorf("invalid length")
 	}

identity/version.go 🔗

@@ -2,7 +2,6 @@ package identity
 
 import (
 	"crypto/rand"
-	"crypto/sha256"
 	"encoding/json"
 	"fmt"
 	"strings"
@@ -106,16 +105,11 @@ func (v *version) Id() entity.Id {
 		if err != nil {
 			panic(err)
 		}
-		v.id = deriveId(data)
+		v.id = entity.DeriveId(data)
 	}
 	return v.id
 }
 
-func deriveId(data []byte) entity.Id {
-	sum := sha256.Sum256(data)
-	return entity.Id(fmt.Sprintf("%x", sum))
-}
-
 // Make a deep copy
 func (v *version) Clone() *version {
 	// copy direct fields
@@ -172,7 +166,7 @@ func (v *version) UnmarshalJSON(data []byte) error {
 		return entity.NewErrNewFormatVersion(aux.FormatVersion)
 	}
 
-	v.id = deriveId(data)
+	v.id = entity.DeriveId(data)
 	v.times = aux.Times
 	v.unixTime = aux.UnixTime
 	v.name = aux.Name
@@ -256,7 +250,7 @@ func (v *version) Write(repo repository.Repo) (repository.Hash, error) {
 	}
 
 	// make sure we set the Id when writing in the repo
-	v.id = deriveId(data)
+	v.id = entity.DeriveId(data)
 
 	return hash, nil
 }