6d37e3250000dee12e193601c4cdbae21e4d099b
braney
  Mon Apr 20 14:59:37 2026 -0700
make assumesHub session portability work for assembly hubs: when the current db is hub_<id>_<genome> and the hub's id differs from the local hubStatus id, remap the db cart variable and any db-keyed cart vars (e.g. position.<db>) along with the hub_<id>_* track settings that were already being renamed. refs #34986

diff --git src/hg/lib/hubConnect.c src/hg/lib/hubConnect.c
index 42f8259c3e1..9afd0e3038d 100644
--- src/hg/lib/hubConnect.c
+++ src/hg/lib/hubConnect.c
@@ -1392,59 +1392,90 @@
         struct slPair *cartVars = cartVarsLike(cart, wildCard);
 
         for(; cartVars; cartVars = cartVars->next)
             {
             char *rest = trackHubSkipHubName(cartVars->name);
             char newVarName[4096];
 
             // add the new visibility/setting
             safef(newVarName, sizeof newVarName, "hub_%d_%s", localHubId, rest);
             cartSetString(cart, newVarName, cartVars->val);
 
             // remove the old visibility/setting
             cartRemove(cart, cartVars->name);
             }
 
+        // if the current db is an assembly hub on this remapped hub,
+        // rewrite the db value and any db-keyed cart vars (e.g. "position.<db>")
+        char oldHubDbPrefix[64];
+        safef(oldHubDbPrefix, sizeof oldHubDbPrefix, "hub_%u_", sessionHubId);
+        char *db = cartOptionalString(cart, "db");
+        if (db != NULL && startsWith(oldHubDbPrefix, db))
+            {
+            char oldDb[4096];
+            char newDb[4096];
+            safef(oldDb, sizeof oldDb, "%s", db);
+            safef(newDb, sizeof newDb, "hub_%u_%s", localHubId, oldDb + strlen(oldHubDbPrefix));
+
+            // rename cart vars whose key ends with ".<oldDb>" (e.g. position.<db>)
+            char dbWildCard[4096];
+            safef(dbWildCard, sizeof dbWildCard, "*.%s", oldDb);
+            struct slPair *dbKeyedVars = cartVarsLike(cart, dbWildCard);
+            for (; dbKeyedVars; dbKeyedVars = dbKeyedVars->next)
+                {
+                int prefixLen = strlen(dbKeyedVars->name) - strlen(oldDb);
+                char newName[4096];
+                safef(newName, sizeof newName, "%.*s%s", prefixLen, dbKeyedVars->name, newDb);
+                cartSetString(cart, newName, dbKeyedVars->val);
+                cartRemove(cart, dbKeyedVars->name);
+                }
+
+            cartSetString(cart, "db", newDb);
+            }
+
         // turn on this remapped hub
         char hubName[4096];
         cartSetString(cart, hgHubConnectRemakeTrackHub, "on");
         safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, localHubId);
         cartSetString(cart, hubName, "1");
 
         // remove the old hub connection
         safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, sessionHubId);
         cartRemove(cart, hubName);
         }
     }
 
 cartRemove(cart, "assumesHub");
 }
 
 char *hubConnectLoadHubs(struct cart *cart)
 /* load the track data hubs.  Set a static global to remember them */
 {
 char *dbSpec = asmAliasFind(cartOptionalString(cart, "db"));
 char *curatedHubPrefix = getCuratedHubPrefix();
 if (dbSpec != NULL)
     lookForCuratedHubs(cart, trackHubSkipHubName(dbSpec), curatedHubPrefix);
 
 char *newDatabase = checkForNew( cart);
 newDatabase = asmAliasFind(newDatabase);
 cartSetString(cart, hgHubConnectRemakeTrackHub, "on");
 
 portHubStatus(cart);
 
+// portHubStatus may have rewritten db to point at a remapped assembly hub id
+dbSpec = asmAliasFind(cartOptionalString(cart, "db"));
+
 struct hubConnectStatus  *hubList =  hubConnectStatusListFromCart(cart, dbSpec);
 
 char *genarkPrefix = cfgOption("genarkHubPrefix");
 if (genarkPrefix && lookForLonelyHubs(cart, hubList, &newDatabase, genarkPrefix))
     hubList = hubConnectStatusListFromCart(cart, dbSpec);
 
 globalHubList = hubList;
 
 return newDatabase;
 }
 
 char *hubNameFromUrl(char *hubUrl)
 /* Given the URL for a hub, return its hub_# name. */
 {
 if (hubUrl == NULL)