dba11b63364870388011d5f04c6563ed440eb2a1
braney
  Thu Sep 24 13:49:56 2026 -0700
quickLift: a container set back to show no longer stays hidden on the target, refs #38198

When hgTracks arrives from a lift (hideTracks), it read a quickLifted
superTrack's state from the cart. It copied the source's bare cart value, such
as wgEncodeReg4, to hub_NNN_wgEncodeReg4 and then removed the bare one. That
had two effects. A container hidden before one lift kept the stored hide after
every later lift. This happened because hgTracks prunes a container value that
equals its default, so a container set back to show left nothing to carry
over. Visiting the target also deleted the source's own setting.

The cart read was added for #37535, when the lifted stanza still ended with
the source's "superTrack on hide". #37969 removed that line, so the stanza is
now correct. On a lift the stanza decides again: any hub_ value for the
container is dropped, and the source's value is left alone.

Also write "visibility show" for the container rather than "visibility hide".
walkTree passed "tvShow" to hTvFromString, which does not know that string and
returns hide.

With this change, a container hidden on the source keeps its earlier stanza on
the target, the same as a hidden track.

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 5a50d3c050b..10ec2358628 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -7693,35 +7693,39 @@
     {
     char *s = cartOptionalString(cart, "knownGene");
     if ((s != NULL) && (differentString(s, "hide")))
         cartSetString(cart, defaultGeneTrack, s);
     }
 
 for (track = trackList; track != NULL; track = track->next)
     {
     // deal with any supertracks we're seeing for the first time
     if (tdbIsSuperTrackChild(track->tdb))
         {
         struct hashEl *hel = NULL;
 
         if ((hel = hashLookup(superTrackHash, track->tdb->parent->track)) == NULL)   // we haven't seen this guy
             {
-            // QuickLifted tracks are exempt from hideTracks -- their visibility is
-            // carried over from the source assembly's cart (and may still be under the
-            // undecorated name until migrated below), so consult the cart, not the URL.
-            boolean superFromCart = !hideTracks ||
-                (trackDbSetting(track->tdb, "quickLiftUrl") != NULL);
+            // hideTracks means we just arrived from a quickLift.  The lift hub has already
+            // written the container the way it is on the source ("superTrack on show"), so
+            // the hub stanza decides, not the cart.  Drop any value an earlier lift left
+            // under the hub name, and leave the source's own undecorated value alone:  that
+            // one belongs to the source assembly, and it is gone anyway whenever the source
+            // container is back at its default.
+            if (hideTracks && (trackDbSetting(track->tdb, "quickLiftUrl") != NULL))
+                cartRemove(cart, track->tdb->parent->track);
+            boolean superFromCart = !hideTracks;
             // first deal with visibility of super track
             char *s = superFromCart ? cartOptionalString(cart, track->tdb->parent->track) : cgiOptionalString(track->tdb->parent->track);
             if (s)
                 {
                 track->tdb->parent->visibility = hTvFromString(s) ;
                 cartSetString(cart, track->tdb->parent->track, s);
                 }
             else if (startsWith("hub_", track->tdb->parent->track))
                 {
                 s = superFromCart ? cartOptionalString( cart, trackHubSkipHubName(track->tdb->parent->track)) : cgiOptionalString( trackHubSkipHubName(track->tdb->parent->track));
                 // the bare name is the native track's if the assembly has one by that name
                 if (s != NULL && !hubTrackOwnsBareName(database, track->tdb->parent->track))
                     s = NULL;
                 if (s)
                     {