We found confusion between data store versions and OS versions, so this
simplifies the system to only use OS version. If there's been no change in the
data store, which is now determined by there being no migrations, then the new
data store will simply be a link to the last version that did have changes.
These are the changes at a high level:
* Remove the data_store_version library and its type, instead using semver::Version
* Cascade this change through migrator, storewolf, update_metadata, and updog
* Remove OS version -> data store version mapping in updog
* Remove the data-store-version file, instead using OS version from bottlerocket-release
* In migrator, just symlink to previous data store if there are no migrations
* In migrator, flip symlinks for current, major, minor, and patch, since any could change
* In storewolf, also create the new patch-level symlink
One change deserves more description. It's an extension of the problem from #644
that only showed up while testing this change, and was made easier to fix by
these changes, so it was done together.
Background: In migrator, we were giving each migration the same source and
target data store. Migrations make whatever changes they want to a
MigrationData, each key of which is then written to the data store.
Problem: Let's say the system has settings A and B. One migration adds setting
C. This is written to the target data store. Another migration tries to
remove setting B. It does so in memory, but B has already been written to the
target by the first migration, so it's to no avail.
Solution: Chain the input and output of migrations in order. The first
migration receives the source data store and adds setting C, writing out to a
*new* data store path it was given. The second migration is given that new
data store as a source; it removes setting B and writes out to another new data
store path it was given. At the end of the chain, the final data store is kept
and the intermediate ones are removed.