Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cards are likely collapsed into a single deck on push operations #109

Closed
langfield opened this issue Nov 10, 2022 · 10 comments · Fixed by #157
Closed

Cards are likely collapsed into a single deck on push operations #109

langfield opened this issue Nov 10, 2022 · 10 comments · Fixed by #157
Labels
bug Something isn't working

Comments

@langfield
Copy link
Owner

It looks like calls to update_note() will collapse cards into whatever deck the single source-of-truth file is in. See below:

ki/ki/__init__.py

Lines 484 to 491 in 44e497f

# Set the deck of the given note, as well as all its cards, and create a
# deck with this name if it doesn't already exist. See the
# comments/docstrings in the implementation of the
# `anki.decks.DeckManager.id()` method.
newdid: int = note.col.decks.id(decknote.deck, create=True)
cids = [c.id for c in note.cards()]
if cids:
note.col.set_deck(cids, newdid)

This is a major bug, and I'm surprised we don't have a test for it yet. It is also slightly difficult to detect, since roundtripping does work so long as we don't make changes to notes locally.

This will require some changes to the diff2() logic, since for every symlink that's been modified, renamed, added, or deleted, we should check both the a_file and b_file for affected cards, and update the decks accordingly using calls to col.set_deck().

@langfield
Copy link
Owner Author

Since the test DSL is mostly finished, writing a test for this bug is now the highest priority! 😡

@langfield
Copy link
Owner Author

langfield commented Sep 24, 2023

Can be fixed by making all cards symlinks. So now there is no special "ground-truth" card anywhere in the repository. We have a .ki/notes/ directory, and here we have a file for each note, where the filename is the guid. The symlinks for each card point to the note file.

This way there are never any dangling symlinks when we move the "ground-truth" card to another deck, because there is none. And thus the symlinks always point to the same thing.

We should probably not try to deduplicate card symlinks in a single deck.

The symlink names will be of the form <sortf>.<card_name>.md. So e.g. aa.Card\ 1.md.

@langfield
Copy link
Owner Author

langfield commented Sep 24, 2023

The existing _push()/write_collection() logic should be refactored so it only diffs at -- .ki/notes/, and we should disable rename detection. (Recall that media files are not handled by parsing diffs).

See: https://stackoverflow.com/a/46807414

Then we'll add another subroutine that does the diffs for the card links. Since card content is completely determined by the note content, this will only exist to set decks. We follow the symlink to get the guid. Then we parse the template name (e.g. Card 1) from the symlink name to figure out which card we're dealing with. Finally we look at where we are in the filesystem to get the target deck. Then we set the appropriate card for that note to that deck. Very simple.

So in fact the DeckNote type should not have a deck field at all. (And hence it should probably be renamed.)

@langfield
Copy link
Owner Author

Okay, but with this new structure, how does a user create a new note from the filesystem?

@langfield
Copy link
Owner Author

langfield commented Sep 25, 2023

Users will have to create new notes with a subcommand, ki mknote <notetype> <title>. It will put the generated cards into whatever deck corresponds to the current working directory. It will error-out if you aren't in a ki repo or you're in an invalid directory like .ki/ or _models/.

We need the title because that's how we know how to generate the card symlink names. E.g. <title>.<template>.md, as mentioned above.

The mknote subcommand will generate a guid for the new note by hashing the string <title>-<random>-<date>, and it will create a file .ki/notes/<guid>.md, and the card symlinks will all point to this file. The note file will have the guid filled-in, so users will no longer have to know to leave it blank, and it will autogenerate the header and the field sections.

@langfield
Copy link
Owner Author

This is becoming stupidly complicated. What if we just forget about the "location of card is the deck" thing and just have a bunch of note files in a flat directory, and each note file has a section:

### Decks
```
Card 1: aa::bb
```

@langfield
Copy link
Owner Author

langfield commented Sep 25, 2023

Or a pre-commit hook that refreshes the filenames of everything in the .ki/notes/ directory. We would generate names of the form <title>--<guid>.md for ki mknote output and <sortf>--<guid>.md for other clone output.

This seems like the most promising approach. It remains to be seen whether there will be too much name churn for git to handle this effectively.

Thus the plan so far should be to implement .ki/notes/<guid>.md and then possibly add names in afterwards.

@langfield
Copy link
Owner Author

langfield commented Sep 26, 2023

Should we even allow cards generated from a single note to be in different decks? Are there any legitimate use-cases for this?

What if instead, we assume that most notes have all their cards in the same deck, and we create a top-level _SPLIT/ directory which contains all the markdown files for notes that have cards in different decks.

Alternatively, for notes whose cards are split between decks, all such cards usually share some superdeck, so perhaps we just include them in their last common ancestor deck. But then how do we represent deck changes? Uh oh, it doesn't work out nicely 😢

@langfield
Copy link
Owner Author

Okay, the plan that seems okay is:

  1. Deprioritize command-line card creation and editing. All we need is for the repo to act as a nice way to merge edits that are mostly made in the Anki client.
  2. Use names everywhere... after implementing stuff with guid filenames (as described above).
  3. Yeah, it isn't really easy to add or rm a note, but we'll just have to live with that for now. We'll print warnings when there's hanging or missing symlinks or missing note sources.
  4. Only do note sources in .ki/notes/ for notes that are actually split between decks. The rest can be done in the obvious way.

@langfield
Copy link
Owner Author

What if we just not support cards in different decks? We can make the program error-out when this happens.

@langfield langfield linked a pull request Oct 1, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
1 participant