dcabcf3e37e0b1e3c71b6a98358c1fb844ca3b8a
braney
  Tue Apr 22 12:26:11 2025 -0700
sessions save a copy of the quickLift hub.

diff --git src/hg/hgSession/hgSession.c src/hg/hgSession/hgSession.c
index e280196d01d..fb151c730fc 100644
--- src/hg/hgSession/hgSession.c
+++ src/hg/hgSession/hgSession.c
@@ -932,32 +932,32 @@
 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, ")");
 sqlUpdate(conn, dy->string);
 dyStringFree(&dy);
 
-/* Prevent modification of custom track collections just saved to namedSessionDb: */
-cartCopyCustomComposites(cart);
+/* Prevent modification of custom track collections or quickLifts just saved to namedSessionDb: */
+cartCopyLocalHubs(cart);
 return useCount;
 }
 
 char *doNewSession(char *userName)
 /* Save current settings in a new named session.
  * Return a message confirming what we did. */
 {
 if (userName == NULL)
     return "Unable to save session -- please log in and try again.";
 struct dyString *dyMessage = dyStringNew(2048);
 char *sessionName = trimSpaces(cartString(cart, hgsNewSessionName));
 if (isEmpty(sessionName))
     return "Error: Unable to save a session without a name.  Please add one and try again.";
 
 char *encSessionName = cgiEncodeFull(sessionName);
@@ -1336,31 +1336,31 @@
     }
 
 hel = cartFindPrefix(cart, hgsLoadPrefix);
 if (hel != NULL)
     {
     char *encSessionName = hel->name + strlen(hgsLoadPrefix);
     char *sessionName = cgiDecodeClone(encSessionName);
     char wildStr[256];
     safef(wildStr, sizeof(wildStr), "%s*", hgsLoadPrefix);
     dyStringPrintf(dyMessage,
 		   "Loaded settings from session <B>%s</B>. %s %s<BR>\n",
 		   htmlEncode(sessionName),
 		   getSessionLink(encUserName, encSessionName),
 		   getSessionEmailLink(encUserName, encSessionName));
     cartLoadUserSession(conn, userName, sessionName, cart, NULL, wildStr);
-    cartCopyCustomComposites(cart);
+    cartCopyLocalHubs(cart);
     hubConnectLoadHubs(cart);
     cartHideDefaultTracks(cart);
     cartCheckForCustomTracks(cart, dyMessage);
     didSomething = TRUE;
     }
 
 cartHelList = cartFindPrefix(cart, hgsDeletePrefix);
 for (hel = cartHelList;  hel != NULL;  hel = hel->next)
     {
     char *encSessionName = hel->name + strlen(hgsDeletePrefix);
     char *sessionName = cgiDecodeClone(encSessionName);
     sqlSafef(query, sizeof(query), "select shared from %s "
       "where userName = '%s' and sessionName = '%s';",
       namedSessionTable, encUserName, encSessionName);
     int shared = sqlQuickNum(conn, query);
@@ -1391,31 +1391,31 @@
  * Return a message confirming what we did. */
 {
 struct sqlConnection *conn = hConnectCentral();
 struct dyString *dyMessage = dyStringNew(1024);
 char *otherUser = trimSpaces(cartString(cart, hgsOtherUserName));
 char *sessionName = trimSpaces(cartString(cart, hgsOtherUserSessionName));
 char *encOtherUser = cgiEncodeFull(otherUser);
 char *encSessionName = cgiEncodeFull(sessionName);
 
 dyStringPrintf(dyMessage,
        "Loaded settings from user <B>%s</B>'s session <B>%s</B>. %s %s",
 	       otherUser, htmlEncode(sessionName),
 	       getSessionLink(otherUser, encSessionName),
 	       getSessionEmailLink(encOtherUser, encSessionName));
 cartLoadUserSession(conn, otherUser, sessionName, cart, NULL, actionVar);
-cartCopyCustomComposites(cart);
+cartCopyLocalHubs(cart);
 hubConnectLoadHubs(cart);
 cartHideDefaultTracks(cart);
 cartCheckForCustomTracks(cart, dyMessage);
 hDisconnectCentral(&conn);
 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);
 
@@ -1506,31 +1506,31 @@
 	}
     dyStringPrintf(dyMessage, "&nbsp;&nbsp;"
 	   "<A HREF=\"%shgTracks?%s=%s\">Browser</A>",
 	   hLocalHostCgiBinUrl(), 
 	   cartSessionVarName(), cartSessionId(cart));
     }
 if (lf != NULL)
     {
     lineFileCarefulNewlines(lf);
     struct dyString *dyLoadMessage = dyStringNew(0);
     boolean ok = cartLoadSettingsFromUserInput(lf, cart, NULL, actionVar, dyLoadMessage);
     lineFileClose(&lf);
     if (ok)
         {
         dyStringAppend(dyMessage, dyLoadMessage->string);
-        cartCopyCustomComposites(cart);
+        cartCopyLocalHubs(cart);
         hubConnectLoadHubs(cart);
         cartHideDefaultTracks(cart);
         cartCheckForCustomTracks(cart, dyMessage);
         }
     else
         {
         dyStringClear(dyMessage);
         dyStringAppend(dyMessage, "<span style='color: red;'><b>"
                        "Unable to load session: </b></span>");
         dyStringAppend(dyMessage, dyLoadMessage->string);
         dyStringAppend(dyMessage, "The uploaded file needs to have been previously saved from the "
                        "<b>Save Settings</b> section.\n");
         // Looking for the words "custom track" in an error string is hokey, returning an enum
         // from cartLoadSettings would be better, but IMO that isn't worth a big refactoring.
         if (stringIn("custom track", dyLoadMessage->string))
@@ -1736,31 +1736,31 @@
  * will be replaced with userdata (hg.conf sessionDataDir) paths.
  * NOTE: this is not intended to be reachable by the UI; it is for a script to update
  * old sessions to use the new sessionData locations. */
 {
 if (userName == NULL)
     return "Unable to re-save session -- please log in and try again.";
 struct sqlConnection *conn = hConnectCentral();
 char *sessionName = trimSpaces(cartString(cart, hgsNewSessionName));
 if (isEmpty(sessionName))
     return "Error: Unable to save a session without a name.  Please add one and try again.";
 
 char *encUserName = cgiEncodeFull(userName);
 char *encSessionName = cgiEncodeFull(sessionName);
 int sharingLevel = getSharingLevel(conn, encUserName, encSessionName);
 cartLoadUserSession(conn, userName, sessionName, cart, NULL, actionVar);
-// Don't cartCopyCustomComposites because we're not going to make any track collection changes
+// Don't cartCopyLocalHubs because we're not going to make any track collection changes
 hubConnectLoadHubs(cart);
 // Some old sessions reference databases that are no longer present, and that triggers an errAbort
 // when cartHideDefaultTracks calls hgTrackDb.  Don't let that stop the process of updating other
 // stuff in the session.
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     cartHideDefaultTracks(cart);
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     fprintf(stderr, "doReSaveSession: Error from cartHideDefaultTracks: '%s'; Continuing...",
             errCatch->message->string);
 errCatchFree(&errCatch);
 struct dyString *dyMessage = dyStringNew(1024);
 dyStringPrintf(dyMessage,
                "Re-saved settings from user <B>%s</B>'s session <B>%s</B> "