fix(vt): round 3 items 3-4 — hidden-prefix-first nav naming + disjoint pickers
Item 3: MossTankRouteProfileStore's per-character auto route file was named
nav_--Name_Server.af (NavPrefix + AutoCharacterFileName) — the "nav_" marker
came BEFORE the "--" hidden prefix, so the whole filename does not start
with "--" and defeats every StartsWith("--") hidden-file check in
VtankProfileDirectory, leaking another character's private route binding
into both the nav and meta pickers. Chose hidden-prefix-first naming
(--nav_Name_Server.af, matching VTank's own "--" convention with the nav_
kind marker second) via a new AutoCharacterFileName(name, server, ext,
marker) overload; applied only to the per-character auto file — named
routes keep their existing nav_Name.af (shared/visible) shape.
Item 4: ListNavigationProfiles and ListMetaProfiles shared the same flat
.af directory with no marker check at all, so each picker returned the
other's files too (a Meta profile appeared in the nav picker and vice
versa). ListNavigationProfiles now requires the nav_ marker;
ListMetaProfiles now excludes it.
Mutation: reverted VtankProfileDirectory.cs and MossTankRouteProfileStore.cs
to HEAD (keeping only the new/changed tests) — the build failed outright
(VtankProfileDirectory has no NavMarker/marker-overload for the new tests to
call), and the two pre-existing tests this round updated
(ListNavigationProfilesFiltersBothReservedPrefixes,
RouteStoreLeavesLegacyJsonUntouchedWhenAfCounterpartExists) independently
failed at runtime against their OLD un-marked/mis-ordered fixtures once
this round's marker/ordering requirement was pinned, confirming both are
exercising real, fixed behavior.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
145bd62503
commit
0398913538
4 changed files with 124 additions and 12 deletions
|
|
@ -375,8 +375,15 @@ internal sealed class MossTankRouteProfileStore
|
|||
// File naming, storage plumbing.
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// Round 3 item 3: the hidden "--" prefix MUST come before the "nav_"
|
||||
// kind marker (--nav_Name_Server.af) — putting the marker first
|
||||
// (nav_--Name_Server.af, the pre-fix shape) means the filename does not
|
||||
// start with "--" at all, defeating the StartsWith("--") hidden-file
|
||||
// check both ListNavigationProfiles and ListMetaProfiles rely on and
|
||||
// leaking this character's private per-character route to every other
|
||||
// character's picker.
|
||||
private string CurrentFileName() => _selected.Equals(ByCharacter, StringComparison.OrdinalIgnoreCase)
|
||||
? NavPrefix + VtankProfileDirectory.AutoCharacterFileName(_characterName, Server, "af")
|
||||
? VtankProfileDirectory.AutoCharacterFileName(_characterName, Server, "af", NavPrefix)
|
||||
: _selected;
|
||||
|
||||
private static string ToFileName(string bareName) =>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,22 @@ internal static class VtankProfileDirectory
|
|||
internal const string DefaultLabel = "[Default]";
|
||||
internal const string NoneLabel = "[None]";
|
||||
|
||||
/// <summary>
|
||||
/// The <c>nav_</c> marker (round 3 items 3/4) that distinguishes a
|
||||
/// stand-alone route <c>.af</c> from a Meta profile sharing the same
|
||||
/// flat <see cref="IPluginHost.VtankProfiles"/> directory and extension
|
||||
/// — metaf's own observed convention for a nav-only <c>.af</c> (see the
|
||||
/// committed <c>nav_*.af</c> fixtures). MUST be checked AFTER stripping
|
||||
/// <see cref="HiddenPrefix"/> when the marker is combined with it (see
|
||||
/// <see cref="AutoCharacterFileName(string,string,string,string)"/>'s
|
||||
/// <c>marker</c> parameter): a hidden per-character route file is named
|
||||
/// <c>--nav_Name_Server.af</c> — hidden prefix FIRST, marker SECOND —
|
||||
/// never <c>nav_--Name_Server.af</c>, which does not start with
|
||||
/// <see cref="HiddenPrefix"/> at all and so defeats every
|
||||
/// <c>StartsWith("--")</c> hidden-file check in this class.
|
||||
/// </summary>
|
||||
internal const string NavMarker = "nav_";
|
||||
|
||||
/// <summary>
|
||||
/// VTank's single per-character default filename
|
||||
/// (<c>uTank2/PluginCore.cs:3863-3865</c>): <c>--Name_Server.ext</c>.
|
||||
|
|
@ -45,6 +61,21 @@ internal static class VtankProfileDirectory
|
|||
string extension) =>
|
||||
$"{HiddenPrefix}{characterName}_{server}.{extension.TrimStart('.')}";
|
||||
|
||||
/// <summary>
|
||||
/// Overload for a per-character auto file that ALSO carries a kind
|
||||
/// marker (currently only <see cref="NavMarker"/>, for
|
||||
/// <see cref="MossTankRouteProfileStore"/>'s route <c>.af</c>): the
|
||||
/// hidden prefix always comes first so the file stays hidden from every
|
||||
/// other character's picker exactly like the unmarked overload above —
|
||||
/// <c>--{marker}Name_Server.ext</c>, e.g. <c>--nav_Name_Server.af</c>.
|
||||
/// </summary>
|
||||
public static string AutoCharacterFileName(
|
||||
string characterName,
|
||||
string server,
|
||||
string extension,
|
||||
string marker) =>
|
||||
$"{HiddenPrefix}{marker}{characterName}_{server}.{extension.TrimStart('.')}";
|
||||
|
||||
/// <summary>
|
||||
/// The longer, trailing-underscore prefix
|
||||
/// (<c>uTank2/PluginCore.cs:933,3866</c>, field <c>dw</c>) that marks a
|
||||
|
|
@ -155,7 +186,10 @@ internal static class VtankProfileDirectory
|
|||
/// VTank's navigation-profile list (<c>l()</c>,
|
||||
/// <c>uTank2/PluginCore.cs:7156-7185</c>): seeds
|
||||
/// <see cref="NoneLabel"/>/<see cref="ByCharacterLabel"/>, then every
|
||||
/// <c>.af</c> file that starts with neither <c>--</c> nor <c>~~</c>.
|
||||
/// <see cref="NavMarker"/>-marked <c>.af</c> file that starts with
|
||||
/// neither <c>--</c> nor <c>~~</c>. Round 3 item 4: a Meta profile and a
|
||||
/// route share this same flat, single-extension directory — without
|
||||
/// the marker check this returned every Meta <c>.af</c> too.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<ProfileEntry> ListNavigationProfiles(IPluginStorage storage)
|
||||
{
|
||||
|
|
@ -171,6 +205,8 @@ internal static class VtankProfileDirectory
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (!fileName.StartsWith(NavMarker, StringComparison.Ordinal))
|
||||
continue;
|
||||
entries.Add(new ProfileEntry(fileName, fileName));
|
||||
}
|
||||
return entries;
|
||||
|
|
@ -180,11 +216,12 @@ internal static class VtankProfileDirectory
|
|||
/// VTank's meta-profile list (<c>ac()</c>,
|
||||
/// <c>uTank2/PluginCore.cs:7187+</c>): seeds
|
||||
/// <see cref="NoneLabel"/>/<see cref="ByCharacterLabel"/>, then every
|
||||
/// non-<c>--</c> file (a meta and a nav profile share the same
|
||||
/// directory and extension here — <c>.af</c> — so callers pass a
|
||||
/// distinguishing sub-extension convention if they need one; VTank
|
||||
/// itself distinguished by the separate <c>.met</c>/<c>.nav</c>
|
||||
/// extensions).
|
||||
/// non-<c>--</c>, non-<see cref="NavMarker"/>-marked file (a meta and a
|
||||
/// nav profile share the same directory and extension here —
|
||||
/// <c>.af</c> — so the marker is what VTank's own separate
|
||||
/// <c>.met</c>/<c>.nav</c> extensions used to provide; round 3 item 4:
|
||||
/// without excluding <see cref="NavMarker"/> files this returned every
|
||||
/// route <c>.af</c> too).
|
||||
/// </summary>
|
||||
public static IReadOnlyList<ProfileEntry> ListMetaProfiles(IPluginStorage storage)
|
||||
{
|
||||
|
|
@ -197,6 +234,8 @@ internal static class VtankProfileDirectory
|
|||
{
|
||||
if (fileName.StartsWith(HiddenPrefix, StringComparison.Ordinal))
|
||||
continue;
|
||||
if (fileName.StartsWith(NavMarker, StringComparison.Ordinal))
|
||||
continue;
|
||||
entries.Add(new ProfileEntry(fileName, fileName));
|
||||
}
|
||||
return entries;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue