Refuse a catalogue in which two entries carry one guid - #139
Merged
Conversation
…ions#812) A guid is a plugin's identity to a Jellyfin server: it names the plugin in the configuration, in the catalogue and on disk. Nothing between a descriptor and the published file asked whether two entries claimed one identity, and three plugin boards shipped the plugin template's own guid, measured across all twelve manifests before any of them had a release. JudgeShared reads the entries the route has built and refuses the run before publish.Place is reached, so a colliding stock leaves the address answering with the file from the last run that finished. Every shared identifier is named at once and each with the entries that carry it, so a stock in which two pairs collide is repaired in one pass. WHAT MAKES THE REFUSAL WORTH MORE THAN THE SHAPE IT LOOKS LIKE. A generator accumulating into a map keyed by guid ships one entry and drops the other with nothing red and nothing said: the file is well formed, deterministic, and missing a plugin. This route builds a slice, so both entries survive as far as here and the run stops instead of publishing them. Watched refusing, twice, on the mistakes somebody makes: the call in Publish deleted go test ./internal/catalogue -count=1 --- FAIL: TestTwoEntriesUnderOneGuidAreRefusedRatherThanPlaced two entries carried one guid and the run exited zero manifest.json: wrote new bytes, carrying 2 plugin(s) and 2 version(s). the carrier count off by one, len(names) < 2 -> < 3 --- FAIL: TestTwoEntriesUnderOneGuidAreRefusedRatherThanPlaced --- FAIL: TestASharedGuidIsRefusedInBothDirections/one_identity_twice one identity twice was accepted Both reverted afterwards. The near-miss is the test beside it: two plugins whose descriptors carry identities of their own are placed, and both entries reach the file. It is there because published() hands every fixture plugin one constant, so a rule refusing any run with two plugins in it would have passed every other test in the package. carrying() is the plant, and it rewrites the guid in the descriptor rather than in the release, because the guid never travels on the release. The comparison is byte-for-byte on the identifier as written. A pair differing only in case reaches the rule as two identifiers; that is a bound rather than a decision, it is stated where the rule is, and where it is argued is the issue above. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Contributes to iderex/operations#812, whose remaining item is that the check for a duplicate guid "belongs in front of the manifest producer and has to make it red".
What was wrong
A guid is a plugin's identity to a Jellyfin server: it names the plugin in the configuration, in the catalogue and on disk. Nothing on the route from a descriptor to the published file asked whether two entries claimed one identity. The instance that produced the issue was measured across all twelve plugin manifests before any of the three had a release:
discover,requestsandinvitesall carried the plugin template's own guid.What this adds
catalogue.JudgeSharedreads the entriesBuildproduced and refuses the run beforepublish.Placeis reached, so a colliding stock leaves the install address answering with the file from the last run that finished. It sits besideJudgeDroppedandJudgeinPublish, in the same position and for the same reason: every refusal is decided before any byte is produced.Every shared identifier is named at once, and each with the entries that carry it, so a stock in which two pairs collide is repaired in one pass rather than one run per pair.
Why this is a refusal rather than a note in the report
A generator that accumulates into a map keyed by guid ships one entry and drops the other, with nothing red and nothing said - the file is well formed, deterministic, and missing a plugin.
manifest/determinism_test.gosays in its own comment that a map keyed by guid is how a generator accumulates. This route builds a slice, so both entries survive as far as this rule, and this is where the run stops instead of publishing them. Either way the manifest is wrong before anybody uses it.Watched refusing
Two mutations, each the mistake somebody actually makes, both reverted afterwards.
The call in
Publishdeleted:The carrier count off by one,
len(names) < 2to< 3:The near-miss, and why it is the load-bearing test
TestTwoPluginsWithIdentitiesOfTheirOwnArePlacedpublishes two plugins whose descriptors carry different guids and asserts both entries reach the file. It is there becausepublished()hands every fixture plugin one package constant, so a rule refusing any run with two plugins in it would have passed every other test in this package.carrying()is the plant: it rewrites the guid in the descriptor body rather than on the release, because the guid never travels on the release - the route reads it out of the asset.The means
Go, in the package that already holds the order the parts run in, judged by the suite that already exists. The rule is a comparison over entries the route has in hand, so it needs no new runtime, no dependency and no parallel apparatus;
go.modis byte-identical after this change.The bound, stated rather than left to be discovered
The comparison is byte-for-byte on the identifier as written. A pair differing only in case, or only in braces, reaches the rule as two identifiers and is not refused. Reading otherwise would refuse pairs no server confuses, which is a judgement about what a server parses rather than about what this repository declares;
internal/identityis where a guid is held to its shape. The bound is written at the rule and argued on iderex/operations#812.What was run
The harness did not run and none of its three requirements was asked for; no leg above depends on any of them. Nothing here reaches the network: every fixture is invented and the only host in one is the domain reserved for documentation.
No second reader
This board has no second reader tonight. The two mutations above and their output stand in place of one.