8fcb2ed43b0ec0060a831894d4cf8eaab95fa466
braney
  Thu Mar 23 12:42:04 2023 -0700
add a mechanism whereby hubStatus id's in a session can be mapped to the
local hubStatus id for that hub

diff --git src/hg/hgSession/hgSession.c src/hg/hgSession/hgSession.c
index 4bbfb5a..18262fd 100644
--- src/hg/hgSession/hgSession.c
+++ src/hg/hgSession/hgSession.c
@@ -755,30 +755,53 @@
 }
 
 static void outIfNotPresent(struct cart *cart, struct dyString *dy, char *track, int tdbVis)
 /* Output default trackDb visibility if it's not mentioned in the cart. */
 {
 char *cartVis = cartOptionalString(cart, track);
 if (cartVis == NULL)
     {
     if (dy)
         dyStringPrintf(dy,"&%s=%s", track, hStringFromTv(tdbVis));
     else
         printf("%s %s\n", track, hStringFromTv(tdbVis));
     }
 }
 
+static void outAttachedHubUrls(struct cart *cart, struct dyString *dy)
+/* output the hubUrls for all attached hubs in the cart. */
+{
+struct hubConnectStatus *statusList = hubConnectStatusListFromCart(cart);
+
+if (statusList == NULL)
+    return;
+
+if (dy)
+    dyStringPrintf(dy,"&assumesHub=");
+else
+    printf("assumesHub ");
+for(; statusList; statusList = statusList->next)
+    {
+    if (dy)
+        dyStringPrintf(dy,"%d=%s ", statusList->id, statusList->hubUrl);
+    else
+        printf("%d=%s ", statusList->id, statusList->hubUrl);
+    }
+if (dy == NULL)
+    printf("\n");
+}
+
 static void outDefaultTracks(struct cart *cart, struct dyString *dy)
 /* Output the default trackDb visibility for all tracks
  * in trackDb if the track is not mentioned in the cart. */
 {
 database = cartString(cart, "db");
 struct trackDb *tdb = NULL;
 // Some old sessions reference databases that are no longer present, and that triggers an errAbort
 // when calling hgTrackDb.  Just move on instead of errAborting.
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     tdb = hTrackDb(database);
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     {
     fprintf(stderr, "outDefaultTracks: Error from hTrackDb: '%s'; Continuing...",
@@ -863,30 +886,33 @@
 sqlUpdate(conn, dy->string);
 
 dyStringClear(dy);
 sqlDyStringPrintf(dy, "INSERT INTO %s ", namedSessionTable);
 sqlDyStringPrintf(dy, "(userName, sessionName, contents, shared, "
                "firstUse, lastUse, useCount");
 if (gotSettings)
     sqlDyStringPrintf(dy, ", settings");
 sqlDyStringPrintf(dy, ") VALUES (");
 sqlDyStringPrintf(dy, "'%s', '%s', ", encUserName, encSessionName);
 sqlDyStringPrintf(dy, "'");
 cleanHgSessionFromCart(cart);
 struct dyString *encoded = dyStringNew(4096);
 cartEncodeState(cart, encoded);
 
+// First output the hubStatus id's for attached trackHubs
+outAttachedHubUrls(cart, encoded);
+
 // Now add all the default visibilities to output.
 outDefaultTracks(cart, encoded);
 
 sqlDyAppendEscaped(dy, encoded->string);
 dyStringFree(&encoded);
 sqlDyStringPrintf(dy, "', ");
 sqlDyStringPrintf(dy, "%d, ", sharingLevel);
 if (firstUse)
     sqlDyStringPrintf(dy, "'%s', ", firstUse);
 else
     sqlDyStringPrintf(dy, "now(), ");
 sqlDyStringPrintf(dy, "now(), %d", useCount);
 if (gotSettings)
     sqlDyStringPrintf(dy, ", '%s'", settings);
 sqlDyStringPrintf(dy, ")");
@@ -1360,30 +1386,33 @@
 return dyStringCannibalize(&dyMessage);
 }
 
 void doSaveLocal()
 /* Output current settings to be saved as a file on the user's machine.
  * Return a message confirming what we did. */
 {
 char *fileName = textOutSanitizeHttpFileName(cartString(cart, hgsSaveLocalFileName));
 char *compressType = cartString(cart, hgsSaveLocalFileCompress);
 struct pipeline *compressPipe = textOutInit(fileName, compressType, NULL);
 
 cleanHgSessionFromCart(cart);
 
 cartDumpHgSession(cart);
 
+// First output the hubStatus id's for attached trackHubs
+outAttachedHubUrls(cart, NULL);
+
 // Now add all the default visibilities to output.
 outDefaultTracks(cart, NULL);
 
 textOutClose(&compressPipe, NULL);
 }
 
 char *doLoad(boolean fromUrl, char *actionVar)
 /* Load settings from a file or URL sent by the user.
  * Return a message confirming what we did. */
 {
 struct dyString *dyMessage = dyStringNew(1024);
 struct lineFile *lf = NULL;
 webPushErrHandlersCartDb(cart, cartUsualString(cart, "db", NULL));
 if (fromUrl)
     {