Skip to content

Commit fd10300

Browse files
tink-botkolaente
authored andcommitted
fix(migration): don't drop TickTick tasks sharing a malformed id
Collapsing unparseable taskIds to 0 meant sortParentsBeforeChildren, which tracked placement by TaskID, treated every zero-id task after the first as already placed and silently dropped it. Track placement by task identity instead so duplicate or zero ids never conflate distinct tasks.
1 parent ebb89ba commit fd10300

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

pkg/modules/migration/ticktick/ticktick.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,16 @@ func sortParentsBeforeChildren(tasks []*tickTickTask) []*tickTickTask {
146146
tasksByID[t.TaskID] = t
147147
}
148148

149-
placed := make(map[tickTickNumber]bool, len(tasks))
149+
// placed is keyed by the task itself rather than by TaskID: malformed
150+
// exports can collapse several taskIds to 0 (see tickTickNumber), and
151+
// keying by ID would treat every zero-ID task after the first as already
152+
// placed and silently drop it.
153+
placed := make(map[*tickTickTask]bool, len(tasks))
150154
result := make([]*tickTickTask, 0, len(tasks))
151155

152156
var place func(t *tickTickTask)
153157
place = func(t *tickTickTask) {
154-
if placed[t.TaskID] {
158+
if placed[t] {
155159
return
156160
}
157161
// If this task has a parent that we know about, place the parent first.
@@ -160,7 +164,7 @@ func sortParentsBeforeChildren(tasks []*tickTickTask) []*tickTickTask {
160164
place(parent)
161165
}
162166
}
163-
placed[t.TaskID] = true
167+
placed[t] = true
164168
result = append(result, t)
165169
}
166170

pkg/modules/migration/ticktick/ticktick_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,3 +846,26 @@ func TestNonNumericNumberColumns(t *testing.T) {
846846
}
847847
assert.Equal(t, int64(1), priority)
848848
}
849+
850+
// TestMultipleTasksWithMalformedIDsAreNotDropped guards against a regression
851+
// where collapsing several unparseable taskIds to 0 caused all but the first
852+
// zero-ID task to be silently dropped by sortParentsBeforeChildren.
853+
func TestMultipleTasksWithMalformedIDsAreNotDropped(t *testing.T) {
854+
tasks := []*tickTickTask{
855+
{TaskID: 0, ProjectName: "Project 1", Title: "First malformed"},
856+
{TaskID: 0, ProjectName: "Project 1", Title: "Second malformed"},
857+
{TaskID: 0, ProjectName: "Project 1", Title: "Third malformed"},
858+
}
859+
860+
sorted := sortParentsBeforeChildren(tasks)
861+
require.Len(t, sorted, 3, "no task with a zero ID should be dropped")
862+
863+
vikunjaTasks := convertTickTickToVikunja(tasks)
864+
titles := []string{}
865+
for _, project := range vikunjaTasks {
866+
for _, task := range project.Tasks {
867+
titles = append(titles, task.Title)
868+
}
869+
}
870+
assert.ElementsMatch(t, []string{"First malformed", "Second malformed", "Third malformed"}, titles)
871+
}

0 commit comments

Comments
 (0)