# todo.merge Merges todos brought in from elsewhere (an imported CSV file, another device) into a list, by id, instead of replacing the whole list. | id is in | result | | --- | --- | | both lists | the **incoming** todo, in the place the current one had | | only `current` | kept as it is | | only `incoming` | appended after the current todos | ## Which copy wins The incoming one. A todo (todo.item) records when it was created and completed but not when it was last edited, so there is no honest way to tell which of two copies is newer. Importing a file is the person saying "these are the versions I want", so the file's row is treated as the newer copy: every field comes from it, done state and timestamps included. ## Order The result is in manual order (todo.sort's `manual`: `order` ascending, ties by array position), renumbered 0 to n-1, as todo.list's `moveTodo` leaves a list: 1. The current todos in their manual order, each replaced by its incoming copy where there is one. A replaced todo keeps its **current** position: the person arranged this list, and the file's `order` is a position in a different list. 2. Then the todos only in `incoming`, in the incoming list's own manual order, so a file's order among its new rows is kept. So a new todo whose file `order` is 0 still goes after the existing ones, and gaps in the current orders close up. ## Errors An id that appears twice in either list is an error (`duplicate id "a" in the incoming list`), because it is ambiguous which copy to keep. The todos are not otherwise checked: todo.import-csv has already checked a file's rows with todo.item's `validateTodo`.