8afc792afaf50aab2d6b83a33ba41b47dbf1df4a max Tue Sep 29 15:51:16 2026 -0700 hgSession: also clear the pending session-load marker before a local-file save The named-session save path already did this; the "save as local file" export path did not, so the marker (and the session name/owner it points at) could ride along into an exported file and resurface on re-import, refs #38399 diff --git src/hg/hgSession/hgSession.c src/hg/hgSession/hgSession.c index bed7f0cb928..3ab009f40af 100644 --- src/hg/hgSession/hgSession.c +++ src/hg/hgSession/hgSession.c @@ -818,30 +818,42 @@ cartRemovePrefix(cart, hgsMakeDownloadPrefix); cartRemovePrefix(cart, hgsDoDownloadPrefix); cartRemovePrefix(cart, hgsDo); cartRemove(cart, hgsOldSessionName); cartRemove(cart, hgsCancel); /* Two of the Save form's own inputs. If they stay in the cart they are stored inside every * session saved afterwards, so one session's description travels in sessions that never had * one. hgsNewSessionShare is left alone on purpose: it has the same problem, but it is also * the only memory of the user's "Allow this session to be loaded by others" choice, and * showSavingOptions() defaults that box to checked. Removing it here would quietly re-check * the box for someone who keeps their sessions private. */ cartRemove(cart, hgsNewSessionName); cartRemove(cart, hgsNewSessionDescription); } +static void clearSessionJustLoadedMarker(struct cart *cart) +/* A pending "session just loaded" marker (and the name/owner it refers to) belongs to the + * live cart's next page view, not to a session's own saved contents. Call this at every + * place that bakes the current cart into a persistent artifact (a named session, a local + * download) -- but not at hgSession's own generic end-of-request cleanup, which must leave + * the marker alone so hgTracks still gets to show the notice on its next page. */ +{ +cartRemove(cart, hgsSessionJustLoaded); +cartRemove(cart, hgsOtherUserSessionName); +cartRemove(cart, hgsOtherUserName); +} + 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. */ @@ -958,35 +970,31 @@ sqlDyStringPrintf(dy, "DELETE FROM %s WHERE userName = '%s' AND " "sessionName = '%s';", namedSessionTable, encUserName, encSessionName); 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); -/* A pending "session just loaded" marker (and the name/owner it refers to) belongs to the - * live cart's next page view, not to a session's own saved contents. */ -cartRemove(cart, hgsSessionJustLoaded); -cartRemove(cart, hgsOtherUserSessionName); -cartRemove(cart, hgsOtherUserName); +clearSessionJustLoadedMarker(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); @@ -1753,30 +1761,31 @@ 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); cleanHgSessionFromCart(cart); +clearSessionJustLoadedMarker(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. */