Skip to content
This repository was archived by the owner on Aug 24, 2024. It is now read-only.

Commit fbb39e1

Browse files
authored
Merge pull request #8 from MichaelMure/update-migration-3
update migration 3, in particular for git-bug/git-bug/pull/767
2 parents 12ba61d + 8475324 commit fbb39e1

22 files changed

+167
-413
lines changed

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.14
44

55
require (
66
github.com/99designs/keyring v1.1.5
7+
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7
78
github.com/blang/semver v3.5.1+incompatible
89
github.com/blevesearch/bleve v1.0.14
910
github.com/dustin/go-humanize v1.0.0
@@ -14,7 +15,9 @@ require (
1415
github.com/pkg/errors v0.9.1
1516
github.com/spf13/cobra v1.0.0
1617
github.com/stretchr/testify v1.6.1
17-
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
18+
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
1819
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
1920
golang.org/x/text v0.3.3
2021
)
22+
23+
replace golang.org/x/crypto => golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2

go.sum

Lines changed: 30 additions & 25 deletions
Large diffs are not rendered by default.

migration3/after/bug/bug.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var def = dag.Definition{
2828

2929
var ClockLoader = dag.ClockLoader(def)
3030

31-
// Bug hold the data of a bug thread, organized in a way close to
31+
// Bug holds the data of a bug thread, organized in a way close to
3232
// how it will be persisted inside Git. This is the data structure
3333
// used to merge two different version of the same Bug.
3434
type Bug struct {

migration3/after/bug/bug_actions.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ func Push(repo repository.Repo, remote string) (string, error) {
2222

2323
// Pull will do a Fetch + MergeAll
2424
// This function will return an error if a merge fail
25-
func Pull(repo repository.ClockedRepo, remote string, author identity.Interface) error {
25+
// Note: an author is necessary for the case where a merge commit is created, as this commit will
26+
// have an author and may be signed if a signing key is available.
27+
func Pull(repo repository.ClockedRepo, remote string, mergeAuthor identity.Interface) error {
2628
_, err := Fetch(repo, remote)
2729
if err != nil {
2830
return err
2931
}
3032

31-
for merge := range MergeAll(repo, remote, author) {
33+
for merge := range MergeAll(repo, remote, mergeAuthor) {
3234
if merge.Err != nil {
3335
return merge.Err
3436
}
@@ -43,7 +45,7 @@ func Pull(repo repository.ClockedRepo, remote string, author identity.Interface)
4345
// MergeAll will merge all the available remote bug
4446
// Note: an author is necessary for the case where a merge commit is created, as this commit will
4547
// have an author and may be signed if a signing key is available.
46-
func MergeAll(repo repository.ClockedRepo, remote string, author identity.Interface) <-chan entity.MergeResult {
48+
func MergeAll(repo repository.ClockedRepo, remote string, mergeAuthor identity.Interface) <-chan entity.MergeResult {
4749
// no caching for the merge, we load everything from git even if that means multiple
4850
// copy of the same entity in memory. The cache layer will intercept the results to
4951
// invalidate entities if necessary.
@@ -54,7 +56,7 @@ func MergeAll(repo repository.ClockedRepo, remote string, author identity.Interf
5456
go func() {
5557
defer close(out)
5658

57-
results := dag.MergeAll(def, repo, identityResolver, remote, author)
59+
results := dag.MergeAll(def, repo, identityResolver, remote, mergeAuthor)
5860

5961
// wrap the dag.Entity into a complete Bug
6062
for result := range results {

migration3/after/bug/op_add_comment.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
3131
snapshot.addActor(op.Author_)
3232
snapshot.addParticipant(op.Author_)
3333

34-
commentId := entity.CombineIds(snapshot.Id(), op.Id())
3534
comment := Comment{
36-
id: commentId,
35+
id: entity.CombineIds(snapshot.Id(), op.Id()),
3736
Message: op.Message,
3837
Author: op.Author_,
3938
Files: op.Files,
@@ -43,7 +42,7 @@ func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
4342
snapshot.Comments = append(snapshot.Comments, comment)
4443

4544
item := &AddCommentTimelineItem{
46-
CommentTimelineItem: NewCommentTimelineItem(commentId, comment),
45+
CommentTimelineItem: NewCommentTimelineItem(comment),
4746
}
4847

4948
snapshot.Timeline = append(snapshot.Timeline, item)
@@ -65,7 +64,7 @@ func (op *AddCommentOperation) Validate() error {
6564
return nil
6665
}
6766

68-
// UnmarshalJSON is a two step JSON unmarshalling
67+
// UnmarshalJSON is a two-steps JSON unmarshalling
6968
// This workaround is necessary to avoid the inner OpBase.MarshalJSON
7069
// overriding the outer op's MarshalJSON
7170
func (op *AddCommentOperation) UnmarshalJSON(data []byte) error {

migration3/after/bug/op_create.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package bug
33
import (
44
"encoding/json"
55
"fmt"
6-
"strings"
76

87
"github.com/MichaelMure/git-bug-migration/migration3/after/entity"
98
"github.com/MichaelMure/git-bug-migration/migration3/after/entity/dag"
@@ -56,9 +55,8 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) {
5655

5756
snapshot.Title = op.Title
5857

59-
commentId := entity.CombineIds(snapshot.Id(), op.Id())
6058
comment := Comment{
61-
id: commentId,
59+
id: entity.CombineIds(snapshot.Id(), op.Id()),
6260
Message: op.Message,
6361
Author: op.Author_,
6462
UnixTime: timestamp.Timestamp(op.UnixTime),
@@ -70,7 +68,7 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) {
7068

7169
snapshot.Timeline = []TimelineItem{
7270
&CreateTimelineItem{
73-
CommentTimelineItem: NewCommentTimelineItem(commentId, comment),
71+
CommentTimelineItem: NewCommentTimelineItem(comment),
7472
},
7573
}
7674
}
@@ -94,11 +92,8 @@ func (op *CreateOperation) Validate() error {
9492
if text.Empty(op.Title) {
9593
return fmt.Errorf("title is empty")
9694
}
97-
if strings.Contains(op.Title, "\n") {
98-
return fmt.Errorf("title should be a single line")
99-
}
100-
if !text.Safe(op.Title) {
101-
return fmt.Errorf("title is not fully printable")
95+
if !text.SafeOneLine(op.Title) {
96+
return fmt.Errorf("title has unsafe characters")
10297
}
10398

10499
if !text.Safe(op.Message) {

migration3/after/bug/op_edit_comment.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
3434
// Todo: currently any message can be edited, even by a different author
3535
// crypto signature are needed.
3636

37-
snapshot.addActor(op.Author_)
37+
// Recreate the Comment Id to match on
38+
commentId := entity.CombineIds(snapshot.Id(), op.Target)
3839

3940
var target TimelineItem
40-
4141
for i, item := range snapshot.Timeline {
42-
if item.Id() == op.Target {
42+
if item.Id() == commentId {
4343
target = snapshot.Timeline[i]
4444
break
4545
}
@@ -51,7 +51,7 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
5151
}
5252

5353
comment := Comment{
54-
id: op.Target,
54+
id: commentId,
5555
Message: op.Message,
5656
Files: op.Files,
5757
UnixTime: timestamp.Timestamp(op.UnixTime),
@@ -62,12 +62,18 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
6262
target.Append(comment)
6363
case *AddCommentTimelineItem:
6464
target.Append(comment)
65+
default:
66+
// somehow, the target matched on something that is not a comment
67+
// we make the op a no-op
68+
return
6569
}
6670

71+
snapshot.addActor(op.Author_)
72+
6773
// Updating the corresponding comment
6874

6975
for i := range snapshot.Comments {
70-
if snapshot.Comments[i].Id() == op.Target {
76+
if snapshot.Comments[i].Id() == commentId {
7177
snapshot.Comments[i].Message = op.Message
7278
snapshot.Comments[i].Files = op.Files
7379
break
@@ -95,7 +101,7 @@ func (op *EditCommentOperation) Validate() error {
95101
return nil
96102
}
97103

98-
// UnmarshalJSON is a two step JSON unmarshalling
104+
// UnmarshalJSON is two steps JSON unmarshalling
99105
// This workaround is necessary to avoid the inner OpBase.MarshalJSON
100106
// overriding the outer op's MarshalJSON
101107
func (op *EditCommentOperation) UnmarshalJSON(data []byte) error {
@@ -138,7 +144,7 @@ func NewEditCommentOp(author identity.Interface, unixTime int64, target entity.I
138144
}
139145
}
140146

141-
// Convenience function to apply the operation
147+
// EditComment is a convenience function to apply the operation
142148
func EditComment(b Interface, author identity.Interface, unixTime int64, target entity.Id, message string) (*EditCommentOperation, error) {
143149
return EditCommentWithFiles(b, author, unixTime, target, message, nil)
144150
}
@@ -152,13 +158,13 @@ func EditCommentWithFiles(b Interface, author identity.Interface, unixTime int64
152158
return editCommentOp, nil
153159
}
154160

155-
// Convenience function to edit the body of a bug (the first comment)
161+
// EditCreateComment is a convenience function to edit the body of a bug (the first comment)
156162
func EditCreateComment(b Interface, author identity.Interface, unixTime int64, message string) (*EditCommentOperation, error) {
157163
createOp := b.FirstOp().(*CreateOperation)
158164
return EditComment(b, author, unixTime, createOp.Id(), message)
159165
}
160166

161-
// Convenience function to edit the body of a bug (the first comment)
167+
// EditCreateCommentWithFiles is a convenience function to edit the body of a bug (the first comment)
162168
func EditCreateCommentWithFiles(b Interface, author identity.Interface, unixTime int64, message string, files []repository.Hash) (*EditCommentOperation, error) {
163169
createOp := b.FirstOp().(*CreateOperation)
164170
return EditCommentWithFiles(b, author, unixTime, createOp.Id(), message, files)

migration3/after/bug/op_set_metadata.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package bug
22

33
import (
44
"encoding/json"
5+
"fmt"
56

67
"github.com/pkg/errors"
78

89
"github.com/MichaelMure/git-bug-migration/migration3/after/entity"
910
"github.com/MichaelMure/git-bug-migration/migration3/after/identity"
11+
"github.com/MichaelMure/git-bug-migration/migration3/after/util/text"
1012
)
1113

1214
var _ Operation = &SetMetadataOperation{}
@@ -43,6 +45,15 @@ func (op *SetMetadataOperation) Validate() error {
4345
return errors.Wrap(err, "target invalid")
4446
}
4547

48+
for key, val := range op.NewMetadata {
49+
if !text.SafeOneLine(key) {
50+
return fmt.Errorf("metadata key is unsafe")
51+
}
52+
if !text.Safe(val) {
53+
return fmt.Errorf("metadata value is not fully printable")
54+
}
55+
}
56+
4657
return nil
4758
}
4859

migration3/after/bug/op_set_title.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ package bug
33
import (
44
"encoding/json"
55
"fmt"
6-
"strings"
76

87
"github.com/MichaelMure/git-bug-migration/migration3/after/entity"
98
"github.com/MichaelMure/git-bug-migration/migration3/after/identity"
10-
"github.com/MichaelMure/git-bug-migration/migration3/after/util/timestamp"
11-
129
"github.com/MichaelMure/git-bug-migration/migration3/after/util/text"
10+
"github.com/MichaelMure/git-bug-migration/migration3/after/util/timestamp"
1311
)
1412

1513
var _ Operation = &SetTitleOperation{}
@@ -49,20 +47,12 @@ func (op *SetTitleOperation) Validate() error {
4947
return fmt.Errorf("title is empty")
5048
}
5149

52-
if strings.Contains(op.Title, "\n") {
53-
return fmt.Errorf("title should be a single line")
54-
}
55-
56-
if !text.Safe(op.Title) {
57-
return fmt.Errorf("title should be fully printable")
58-
}
59-
60-
if strings.Contains(op.Was, "\n") {
61-
return fmt.Errorf("previous title should be a single line")
50+
if !text.SafeOneLine(op.Title) {
51+
return fmt.Errorf("title has unsafe characters")
6252
}
6353

64-
if !text.Safe(op.Was) {
65-
return fmt.Errorf("previous title should be fully printable")
54+
if !text.SafeOneLine(op.Was) {
55+
return fmt.Errorf("previous title has unsafe characters")
6656
}
6757

6858
return nil

migration3/after/bug/operation.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func idOperation(op Operation, base *OpBase) entity.Id {
7171
return base.id
7272
}
7373

74-
func operationUnmarshaller(author identity.Interface, raw json.RawMessage) (dag.Operation, error) {
74+
func operationUnmarshaller(author identity.Interface, raw json.RawMessage, resolver identity.Resolver) (dag.Operation, error) {
7575
var t struct {
7676
OperationType OperationType `json:"type"`
7777
}
@@ -135,7 +135,7 @@ func operationUnmarshaller(author identity.Interface, raw json.RawMessage) (dag.
135135
// OpBase implement the common code for all operations
136136
type OpBase struct {
137137
OperationType OperationType `json:"type"`
138-
Author_ identity.Interface `json:"author"`
138+
Author_ identity.Interface `json:"-"` // not serialized
139139
// TODO: part of the data model upgrade, this should eventually be a timestamp + lamport
140140
UnixTime int64 `json:"timestamp"`
141141
Metadata map[string]string `json:"metadata,omitempty"`
@@ -178,7 +178,6 @@ func (base *OpBase) UnmarshalJSON(data []byte) error {
178178

179179
aux := struct {
180180
OperationType OperationType `json:"type"`
181-
Author json.RawMessage `json:"author"`
182181
UnixTime int64 `json:"timestamp"`
183182
Metadata map[string]string `json:"metadata,omitempty"`
184183
Nonce []byte `json:"nonce"`
@@ -188,14 +187,7 @@ func (base *OpBase) UnmarshalJSON(data []byte) error {
188187
return err
189188
}
190189

191-
// delegate the decoding of the identity
192-
author, err := identity.UnmarshalJSON(aux.Author)
193-
if err != nil {
194-
return err
195-
}
196-
197190
base.OperationType = aux.OperationType
198-
base.Author_ = author
199191
base.UnixTime = aux.UnixTime
200192
base.Metadata = aux.Metadata
201193
base.Nonce = aux.Nonce

migration3/after/bug/timeline.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
type TimelineItem interface {
13-
// ID return the identifier of the item
13+
// Id return the identifier of the item
1414
Id() entity.Id
1515
}
1616

@@ -26,6 +26,7 @@ type CommentHistoryStep struct {
2626

2727
// CommentTimelineItem is a TimelineItem that holds a Comment and its edition history
2828
type CommentTimelineItem struct {
29+
// id should be the same as in Comment
2930
id entity.Id
3031
Author identity.Interface
3132
Message string
@@ -35,9 +36,9 @@ type CommentTimelineItem struct {
3536
History []CommentHistoryStep
3637
}
3738

38-
func NewCommentTimelineItem(ID entity.Id, comment Comment) CommentTimelineItem {
39+
func NewCommentTimelineItem(comment Comment) CommentTimelineItem {
3940
return CommentTimelineItem{
40-
id: ID,
41+
id: comment.id,
4142
Author: comment.Author,
4243
Message: comment.Message,
4344
Files: comment.Files,

migration3/after/entity/dag/entity.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ const editClockPattern = "%s-edit"
2121

2222
// Definition hold the details defining one specialization of an Entity.
2323
type Definition struct {
24-
// the name of the entity (bug, pull-request, ...)
24+
// the name of the entity (bug, pull-request, ...), for human consumption
2525
Typename string
26-
// the Namespace in git (bugs, prs, ...)
26+
// the Namespace in git references (bugs, prs, ...)
2727
Namespace string
2828
// a function decoding a JSON message into an Operation
29-
OperationUnmarshaler func(author identity.Interface, raw json.RawMessage) (Operation, error)
29+
OperationUnmarshaler func(author identity.Interface, raw json.RawMessage, resolver identity.Resolver) (Operation, error)
3030
// the expected format version number, that can be used for data migration/upgrade
3131
FormatVersion uint
3232
}
@@ -121,7 +121,7 @@ func read(def Definition, repo repository.ClockedRepo, resolver identity.Resolve
121121

122122
// Next step is to:
123123
// 1) read the operationPacks
124-
// 2) make sure that the clocks causality respect the DAG topology.
124+
// 2) make sure that clocks causality respect the DAG topology.
125125

126126
oppMap := make(map[repository.Hash]*operationPack)
127127
var opsCount int
@@ -205,7 +205,7 @@ func read(def Definition, repo repository.ClockedRepo, resolver identity.Resolve
205205
if oppSlice[i].EditTime != oppSlice[j].EditTime {
206206
return oppSlice[i].EditTime < oppSlice[j].EditTime
207207
}
208-
// We have equal EditTime, which means we have concurrent edition over different machines and we
208+
// We have equal EditTime, which means we have concurrent edition over different machines, and we
209209
// can't tell which one came first. So, what now? We still need a total ordering and the most stable possible.
210210
// As a secondary ordering, we can order based on a hash of the serialized Operations in the
211211
// operationPack. It doesn't carry much meaning but it's unbiased and hard to abuse.

migration3/after/entity/dag/entity_actions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func MergeAll(def Definition, repo repository.ClockedRepo, resolver identity.Res
8989
return out
9090
}
9191

92-
// merge perform a merge to make sure a local Entity is up to date.
92+
// merge perform a merge to make sure a local Entity is up-to-date.
9393
// See MergeAll for more details.
9494
func merge(def Definition, repo repository.ClockedRepo, resolver identity.Resolver, remoteRef string, author identity.Interface) entity.MergeResult {
9595
id := entity.RefToId(remoteRef)

0 commit comments

Comments
 (0)