From 5901cf64b4876030777cacab205e19c8e20e7e5e Mon Sep 17 00:00:00 2001 From: konrad Date: Tue, 18 Feb 2020 22:00:54 +0000 Subject: [PATCH] Fix inserting task structure with related tasks (#142) Fix typo Fix creating related tasks Add better logging Fix inserting task structure with related tasks Co-authored-by: kolaente Reviewed-on: https://kolaente.dev/vikunja/api/pulls/142 --- .../migration/create_from_structure.go | 36 ++++++++- .../migration/create_from_structure_test.go | 80 +++++++++++++++++++ pkg/modules/migration/main_test.go | 40 ++++++++++ .../migration/wunderlist/wunderlist.go | 5 +- 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 pkg/modules/migration/create_from_structure_test.go create mode 100644 pkg/modules/migration/main_test.go diff --git a/pkg/modules/migration/create_from_structure.go b/pkg/modules/migration/create_from_structure.go index 312941f54..903ee08a2 100644 --- a/pkg/modules/migration/create_from_structure.go +++ b/pkg/modules/migration/create_from_structure.go @@ -18,6 +18,7 @@ package migration import ( "bytes" + "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/user" "io/ioutil" @@ -27,6 +28,8 @@ import ( // (Namespaces, tasks, etc. Even attachments and relations.) func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err error) { + log.Debugf("[creating structure] Creating %d namespaces", len(str)) + // Create all namespaces for _, n := range str { err = n.Create(user) @@ -34,6 +37,9 @@ func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err return } + log.Debugf("[creating structure] Created namespace %d", n.ID) + log.Debugf("[creating structure] Creating %d lists", len(n.Lists)) + // Create all lists for _, l := range n.Lists { // The tasks slice is going to be reset during the creation of the list so we rescue it here to be able @@ -46,6 +52,9 @@ func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err return } + log.Debugf("[creating structure] Created list %d", l.ID) + log.Debugf("[creating structure] Creating %d tasks", len(tasks)) + // Create all tasks for _, t := range tasks { t.ListID = l.ID @@ -54,31 +63,49 @@ func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err return } + log.Debugf("[creating structure] Created task %d", t.ID) + if len(t.RelatedTasks) > 0 { + log.Debugf("[creating structure] Creating %d related task kinds", len(t.RelatedTasks)) + } + // Create all relation for each task for kind, tasks := range t.RelatedTasks { - // First create the related tasks if they does not exist + + if len(tasks) > 0 { + log.Debugf("[creating structure] Creating %d related tasks for kind %v", len(tasks), kind) + } + for _, rt := range tasks { + // First create the related tasks if they do not exist if rt.ID == 0 { + rt.ListID = t.ListID err = rt.Create(user) if err != nil { return } + log.Debugf("[creating structure] Created related task %d", rt.ID) } // Then create the relation taskRel := &models.TaskRelation{ - TaskID: rt.ID, - OtherTaskID: t.ID, + TaskID: t.ID, + OtherTaskID: rt.ID, RelationKind: kind, } err = taskRel.Create(user) if err != nil { return } + + log.Debugf("[creating structure] Created task relation between task %d and %d", t.ID, rt.ID) + } } // Create all attachments for each task + if len(t.Attachments) > 0 { + log.Debugf("[creating structure] Creating %d attachments", len(t.Attachments)) + } for _, a := range t.Attachments { // Check if we have a file to create if len(a.File.FileContent) > 0 { @@ -88,11 +115,14 @@ func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err if err != nil { return } + log.Debugf("[creating structure] Created new attachment %d", a.ID) } } } } } + log.Debugf("[creating structure] Done inserting new task structure") + return nil } diff --git a/pkg/modules/migration/create_from_structure_test.go b/pkg/modules/migration/create_from_structure_test.go new file mode 100644 index 000000000..73a0eb666 --- /dev/null +++ b/pkg/modules/migration/create_from_structure_test.go @@ -0,0 +1,80 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018-2020 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package migration + +import ( + "code.vikunja.io/api/pkg/db" + "code.vikunja.io/api/pkg/files" + "code.vikunja.io/api/pkg/models" + "code.vikunja.io/api/pkg/user" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestInsertFromStructure(t *testing.T) { + u := &user.User{ + ID: 1, + } + t.Run("normal", func(t *testing.T) { + db.LoadAndAssertFixtures(t) + testStructure := []*models.NamespaceWithLists{ + { + Namespace: models.Namespace{ + Name: "Test1", + Description: "Lorem Ipsum", + }, + Lists: []*models.List{ + { + Title: "Testlist1", + Description: "Something", + Tasks: []*models.Task{ + { + Text: "Task1", + Description: "Lorem", + }, + { + Text: "Task with related tasks", + RelatedTasks: map[models.RelationKind][]*models.Task{ + models.RelationKindSubtask: { + { + Text: "Related to task with related task", + Description: "As subtask", + }, + }, + }, + }, + { + Text: "Task with attachments", + Attachments: []*models.TaskAttachment{ + { + File: &files.File{ + Name: "testfile", + Size: 4, + FileContent: []byte{1, 2, 3, 4}, + }, + }, + }, + }, + }, + }, + }, + }, + } + err := InsertFromStructure(testStructure, u) + assert.NoError(t, err) + }) +} diff --git a/pkg/modules/migration/main_test.go b/pkg/modules/migration/main_test.go new file mode 100644 index 000000000..75e6462ae --- /dev/null +++ b/pkg/modules/migration/main_test.go @@ -0,0 +1,40 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018-2020 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package migration + +import ( + "code.vikunja.io/api/pkg/config" + "code.vikunja.io/api/pkg/files" + "code.vikunja.io/api/pkg/models" + "code.vikunja.io/api/pkg/user" + "os" + "testing" +) + +// TestMain is the main test function used to bootstrap the test env +func TestMain(m *testing.M) { + // Set default config + config.InitDefaultConfig() + // We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly + config.ServiceRootpath.Set(os.Getenv("VIKUNJA_SERVICE_ROOTPATH")) + + // Some tests use the file engine, so we'll need to initialize that + files.InitTests() + user.InitTests() + models.SetupTests() + os.Exit(m.Run()) +} diff --git a/pkg/modules/migration/wunderlist/wunderlist.go b/pkg/modules/migration/wunderlist/wunderlist.go index b802fcfc2..6f09dc99c 100644 --- a/pkg/modules/migration/wunderlist/wunderlist.go +++ b/pkg/modules/migration/wunderlist/wunderlist.go @@ -459,11 +459,14 @@ func (w *Migration) Migrate(user *user.User) (err error) { log.Debugf("[Wunderlist migration] Insert data into db for user %d", user.ID) err = migration.InsertFromStructure(fullVikunjaHierachie, user) + if err != nil { + return err + } log.Debugf("[Wunderlist migration] Done inserting data into db for user %d", user.ID) log.Debugf("[Wunderlist migration] Wunderlist migration for user %d done", user.ID) - return err + return nil } // AuthURL returns the url users need to authenticate against