9602d19ee87ad78e36ba6970cf4372937406d170
braney
  Thu Sep 7 15:57:32 2017 -0700
copy hgCollection hubs when saved or restored from sessions

diff --git src/hg/lib/cart.c src/hg/lib/cart.c
index 21eca3c..d606be5 100644
--- src/hg/lib/cart.c
+++ src/hg/lib/cart.c
@@ -17,30 +17,31 @@
 #include "hdb.h"
 #include "jksql.h"
 #include "jsHelper.h"
 #include "trashDir.h"
 #ifndef GBROWSE
 #include "customFactory.h"
 #include "googleAnalytics.h"
 #include "wikiLink.h"
 #endif /* GBROWSE */
 #include "hgMaf.h"
 #include "hui.h"
 #include "geoMirror.h"
 #include "hubConnect.h"
 #include "trackHub.h"
 #include "cgiApoptosis.h"
+#include "customComposite.h"
 
 static char *sessionVar = "hgsid";	/* Name of cgi variable session is stored in. */
 static char *positionCgiName = "position";
 
 DbConnector cartDefaultConnector = hConnectCart;
 DbDisconnect cartDefaultDisconnector = hDisconnectCart;
 
 static void hashUpdateDynamicVal(struct hash *hash, char *name, void *val)
 /* Val is a dynamically allocated (freeMem-able) entity to put
  * in hash.  Override existing hash item with that name if any.
  * Otherwise make new hash item. */
 {
 struct hashEl *hel = hashLookup(hash, name);
 if (hel == NULL)
     hashAdd(hash, name, val);
@@ -289,38 +290,91 @@
 struct dyString *dy = dyStringNew(1024);
 int useCount;
 sqlDyStringPrintf(dy, "SELECT useCount FROM %s "
 	       "WHERE userName = '%s' AND sessionName = '%s';",
 	       namedSessionTable, encUserName, encSessionName);
 useCount = sqlQuickNum(conn, dy->string) + 1;
 dyStringClear(dy);
 sqlDyStringPrintf(dy, "UPDATE %s SET useCount = %d, lastUse=now() "
 	       "WHERE userName = '%s' AND sessionName = '%s';",
 	       namedSessionTable, useCount, encUserName, encSessionName);
 sqlUpdate(conn, dy->string);
 dyStringFree(&dy);
 }
 
 #ifndef GBROWSE
+static void copyCustomComposites(struct cart *cart, struct hashEl *el)
+/* Copy a set of custom composites to a new hub file. Update the 
+ * relevant cart variables. */
+{
+struct tempName hubTn;
+char *hubFileVar = cloneString(el->name);
+char *db = el->name + sizeof(CUSTOM_COMPOSITE_SETTING);
+char *oldHubFileName = el->val;
+trashDirDateFile(&hubTn, "hgComposite", "hub", ".txt");
+char *newHubFileName = cloneString(hubTn.forCgi);
+
+copyFile(oldHubFileName, newHubFileName);
+
+char *errorMessage;
+unsigned oldHubId =  hubFindOrAddUrlInStatusTable(db, cart, oldHubFileName, &errorMessage);
+unsigned newHubId =  hubFindOrAddUrlInStatusTable(db, cart, newHubFileName, &errorMessage);
+
+// need to change hgHubConnect.hub.#hubNumber# (connected hubs)
+struct slPair *hv, *hubVarList = cartVarsWithPrefix(cart, hgHubConnectHubVarPrefix);
+char buffer[4096];
+for(hv = hubVarList; hv; hv = hv->next)
+    {
+    unsigned hubId = sqlUnsigned(hv->name + strlen(hgHubConnectHubVarPrefix));
+    
+    if (hubId == oldHubId)
+        {
+        cartRemove(cart, hv->name);
+        safef(buffer, sizeof buffer, "%s%d", hgHubConnectHubVarPrefix, newHubId);
+        cartSetString(cart, buffer, "1");
+        }
+    }
+
+// need to change hub_#hubNumber#* (track visibilities)
+safef(buffer, sizeof buffer, "%s%d_", hubTrackPrefix, oldHubId);
+hubVarList = cartVarsWithPrefix(cart, buffer);
+for(hv = hubVarList; hv; hv = hv->next)
+    {
+    char *name = hv->name + strlen(buffer);
+    safef(buffer, sizeof buffer, "%s%d_%s", hubTrackPrefix, newHubId, name);
+    cartSetString(cart, buffer, cloneString(hv->val));
+    cartRemove(cart, hv->name);
+    }
+
+// need to change hgtgroup_hub_#hubNumber# (blue bar open )
+// need to change expOrder_hub_#hubNumber#, simOrder_hub_#hubNumber# (sorting)
+
+// need to change trackHubs #hubNumber#   
+cartSetString(cart, hgHubConnectRemakeTrackHub, "on");
+cartSetString(cart, hubFileVar, newHubFileName);
+}
+
 void cartCopyCustomTracks(struct cart *cart)
 /* If cart contains any live custom tracks, save off a new copy of them,
  * to prevent clashes by multiple uses of the same session.  */
 {
 struct hashEl *el, *elList = hashElListHash(cart->hash);
 
 for (el = elList; el != NULL; el = el->next)
     {
+    if (startsWith(CUSTOM_COMPOSITE_SETTING, el->name))
+        copyCustomComposites(cart, el);
     if (startsWith(CT_FILE_VAR_PREFIX, el->name))
 	{
 	char *db = &el->name[strlen(CT_FILE_VAR_PREFIX)];
 	struct slName *browserLines = NULL;
 	struct customTrack *ctList = NULL;
 	char *ctFileName = (char *)(el->val);
 	if (fileExists(ctFileName))
 	    ctList = customFactoryParseAnyDb(db, ctFileName, TRUE, &browserLines);
         /* Save off only if the custom tracks are live -- if none are live,
          * leave cart variables in place so hgSession can detect and inform
          * the user. */
 	if (ctList)
 	    {
 	    struct customTrack *ct;
 	    static struct tempName tn;