Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
fix(daemon): merge from heads
Browse files Browse the repository at this point in the history
  • Loading branch information
juligasa committed May 16, 2024
1 parent 50e0fd4 commit 7c852b9
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 318 deletions.
65 changes: 16 additions & 49 deletions backend/daemon/api/documents/v1alpha/documents.go
Original file line number Diff line number Diff line change
Expand Up @@ -954,76 +954,43 @@ func (api *Server) MergeChanges(ctx context.Context, in *documents.MergeChangesR
return nil, err
}

if in.TargetDocumentId == "" {
return nil, fmt.Errorf("Target ID is mandatory")
if len(in.Versions) < 2 {
return nil, fmt.Errorf("At least two versions are necessary for merging")
}
eid := hyper.EntityID(in.TargetDocumentId)

source, err := hyper.Version(in.SourceDocumentVersion).Parse()
if err != nil {
return nil, err
allHeads := []cid.Cid{}
for _, version := range in.Versions {
heads, err := hyper.Version(version).Parse()
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "unable to parse version %s: %v", version, err)
}
allHeads = append(allHeads, heads...)
}

doc, err := api.CreateDraft(ctx, &documents.CreateDraftRequest{
ExistingDocumentId: in.TargetDocumentId,
Version: in.TargetDocumentVersion,
})
if err != nil {
return nil, err
}
if doc.Id != eid.String() {
return nil, fmt.Errorf("Internal error. Draft entity and doc don't match")
}
entity, err := api.blobs.LoadEntity(ctx, eid)
entity, err := api.blobs.LoadEntityFromHeads(ctx, hyper.EntityID(in.Id), allHeads...)
if err != nil {
return nil, err
}
ch, err := api.blobs.GetDraft(ctx, eid)
if err != nil {
return nil, err
}

OUTER:
for _, dep := range source {
for _, alreadyDep := range ch.Deps {
if dep == alreadyDep {
continue OUTER
}
}
ch.Deps = append(ch.Deps, dep)
if entity == nil {
return nil, fmt.Errorf("void entity after applying all versions")
}

del, err := api.getDelegation(ctx)
if err != nil {
return nil, err
}

hb, err := entity.CreateChange(entity.NextTimestamp(), me.DeviceKey(), del, map[string]any{
// TODO(juligasa): Remove this and add in terra.go NewChange if deps>1 and no patch don't error since its a merge
"isDraft": true,
}, hyper.WithDeps(ch.Deps), hyper.WithAction(hyper.ActionUpdate))
hb, err := entity.CreateChange(entity.NextTimestamp(), me.DeviceKey(), del, nil, hyper.WithAction(hyper.ActionUpdate))

if err != nil {
return nil, err
}
/*
_, err = api.UpdateDraft(ctx, &documents.UpdateDraftRequest{
DocumentId: eid.String(),
Changes: hb.Decoded,
})
if err != nil {
return nil, err
}*/
if err := api.blobs.SaveDraftBlob(ctx, eid, hb); err != nil {

if err := api.blobs.SaveDraftBlob(ctx, entity.ID(), hb); err != nil {
return nil, err
}

return api.GetDraft(ctx, &documents.GetDraftRequest{
DocumentId: eid.String(),
DocumentId: entity.ID().String(),
})

//return nil, status.Errorf(codes.Unimplemented, "Merge functionality is not implemented yet"+c.String())

}

func (api *Server) getMe() (core.Identity, error) {
Expand Down
67 changes: 19 additions & 48 deletions backend/daemon/api/documents/v1alpha/documents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,78 +554,49 @@ func TestAPIPublishDraft_E2E(t *testing.T) {
}

func TestMerge(t *testing.T) {
//t.Skip("Not ready yet")
t.Parallel()

api := newTestDocsAPI(t, "alice")
ctx := context.Background()

draftTarget, err := api.CreateDraft(ctx, &documents.CreateDraftRequest{})
draft, err := api.CreateDraft(ctx, &documents.CreateDraftRequest{})
require.NoError(t, err)
draftTarget = updateDraft(ctx, t, api, draftTarget.Id, []*documents.DocumentChange{
{Op: &documents.DocumentChange_SetTitle{SetTitle: "My new document title"}},

updated := updateDraft(ctx, t, api, draft.Id, []*documents.DocumentChange{
{Op: &documents.DocumentChange_SetTitle{SetTitle: "Fisrt Doc"}},
{Op: &documents.DocumentChange_MoveBlock_{MoveBlock: &documents.DocumentChange_MoveBlock{BlockId: "b1"}}},
{Op: &documents.DocumentChange_ReplaceBlock{ReplaceBlock: &documents.Block{
Id: "b1",
Type: "statement",
Text: "Hello world!",
Text: "Hello world 1!",
}}},
})
require.NoError(t, err)
require.NotNil(t, draftTarget)
targetDoc, err := api.PublishDraft(ctx, &documents.PublishDraftRequest{DocumentId: draftTarget.Id})
require.NoError(t, err)
require.NotNil(t, targetDoc)

if diff := cmp.Diff(draftTarget, targetDoc.Document, testutil.ExportedFieldsFilter(), cmpopts.IgnoreFields(documents.Document{}, "PublishTime")); diff != "" {
t.Log(diff)
t.Fatal("targetDoc doc must match its final draft")
}

draftSource, err := api.CreateDraft(ctx, &documents.CreateDraftRequest{
ExistingDocumentId: targetDoc.Document.Id,
pub1, err := api.PublishDraft(ctx, &documents.PublishDraftRequest{
DocumentId: updated.Id,
})
require.NoError(t, err)

require.True(t, draftSource.UpdateTime.AsTime().After(targetDoc.Document.UpdateTime.AsTime()), "draft update time must be greater than previous publication")

draftSource = updateDraft(ctx, t, api, draftSource.Id, []*documents.DocumentChange{
{Op: &documents.DocumentChange_DeleteBlock{DeleteBlock: "b1"}},
{Op: &documents.DocumentChange_MoveBlock_{MoveBlock: &documents.DocumentChange_MoveBlock{BlockId: "b2"}}},
draft, err = api.CreateDraft(ctx, &documents.CreateDraftRequest{})
require.NoError(t, err)
updated2 := updateDraft(ctx, t, api, draft.Id, []*documents.DocumentChange{
{Op: &documents.DocumentChange_SetTitle{SetTitle: "Second Doc"}},
{Op: &documents.DocumentChange_MoveBlock_{MoveBlock: &documents.DocumentChange_MoveBlock{BlockId: "b1"}}},
{Op: &documents.DocumentChange_ReplaceBlock{ReplaceBlock: &documents.Block{
Id: "b2",
Id: "b1",
Type: "statement",
Text: "Hello updated!",
Text: "Hello world 2!",
}}},
})

sourceDoc, err := api.PublishDraft(ctx, &documents.PublishDraftRequest{DocumentId: draftSource.Id})
require.NoError(t, err)
require.NotNil(t, sourceDoc)

drafts, err := api.ListDrafts(ctx, &documents.ListDraftsRequest{})
require.NoError(t, err)
require.Len(t, drafts.Documents, 0)

pubs, err := api.ListPublications(ctx, &documents.ListPublicationsRequest{})
pub2, err := api.PublishDraft(ctx, &documents.PublishDraftRequest{
DocumentId: updated2.Id,
})
require.NoError(t, err)
require.Len(t, pubs.Publications, 1)

sourceDoc.Document.Children = nil

testutil.StructsEqual(sourceDoc, pubs.Publications[0]).
IgnoreFields(documents.Document{}, "Version", "PreviousVersion"). // Listed pubs don't have those fields
IgnoreFields(documents.Publication{}, "Version").
Compare(t, "publication in the list must be the same as published")

mergedPub, err := api.MergeChanges(ctx, &documents.MergeChangesRequest{
SourceDocumentVersion: sourceDoc.Document.Version,
TargetDocumentId: targetDoc.Document.Id,
TargetDocumentVersion: targetDoc.Document.Version,
Versions: []string{pub1.Version, pub2.Version},
})
require.NoError(t, err)
require.Equal(t, targetDoc.Document.Id, mergedPub.Id)
require.Equal(t, sourceDoc.Document.Version, mergedPub.PreviousVersion)
require.Equal(t, updated2.Version, mergedPub.PreviousVersion)
}
func TestAPIUpdateDraft_WithList(t *testing.T) {
api := newTestDocsAPI(t, "alice")
Expand Down
Loading

0 comments on commit 7c852b9

Please sign in to comment.