Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
@siimav reports that many RP-1 users have been having problems with
TexturesUnlimited
andROLib
when installing via CKAN, which have been attributed to some speculated property of the exFAT filesystem (generally used for thumb drives):I suspect it's not sorting by creation date per se (since why would Microsoft have bothered to do that, just for exFAT?), but rather just returning the files in disk order, which would correspond to the order in which they were created on exFAT. If that's the case, then "normal" listing behavior for other filesystems may also be disk order (simpler/more consistent code in the kernel), but maybe the OS sorts the files alphanumerically at time of creation, since traditional hard drives don't have limits to the number of times they can be written the way flash drives do? In other words:
We're still looking for confirmation of this or any other similar explanation.
Regardless of how that search turns out, this is something I've thought about doing anyway, since it makes a big changeset more similar to a concatenation of the smaller changesets that it contains. In other words, if
B
depends onA
, I could installA
in one changeset andB
in a later one, but I couldn't installB
by itself first; so if I install both together in one changeset, it likewise makes sense forA
to be installed beforeB
.Changes
RelationshipResolver
now tracks multiple reasons per moduleRelationshipResolver.ReasonFor
is renamedReasonsFor
and returns aList
instead of one valueRelationshipResolver
,Reasons.Add
is replaced by calling a newAddReason
function that adds or appends to aList
RelationshipResolver
now adds a reason when we find that a dependency is satisfied by a mod already in the list, so all relationships will be representedRelationshipResolver.ReasonStringFor
was not in use and is removedRelationshipResolver.ModList
now returns its mods in an ordering based on dependencies instead of the random order of aHashSet
's keys (see below)ModChange
now also tracks multiple reasonsModChange.Description
calls a newSelectionReason.DescribeWith
function to merge all dependency reasons into one comma-delimited listThe sorting algorithm
The goal is for a dependency to be installed before its depending mods, which implicitly includes indirect dependencies. This is not well suited to a traditional
.Sort()
call because given any two mods, you can't necessarily tell which one should go first without checking all of the intermediary dependency mods. So instead we use a procedural alrorithm based around an insertion sort.First we sort the mods in ascending order of how many dependencies they have (so mods with no dependencies float to the top and are installed first), then alphanumerically by name (so the list doesn't look completely random on casual inspection).
Then we step through that list module by module and perform an insertion sort into what will be our final list. If the module we're inserting has an install reason indicating a dependency on any of the mods already in the final list, then we insert it before the first such dependency. Otherwise we add it to the end.
Circular dependencies complicate this; if
A
depends onB
andB
depends onA
, then either ordering of those two mods would be acceptable. I don't know exactly what to do about that, so I'm just letting it pick whatever ordering it likes for those mods using the same logic as for everything else.As a special case, user-requested mods are not sorted before non-user-requested mods, even if there is a dependency relationship, since we know they weren't pulled in as dependencies. This way you can see the ones you picked at the bottom, even if they have circular dependencies with other mods.
For confirmation that this puts
TexturesUnlimited
beforeROLib
: