6629bda6c730982c3e4602ec78ff3b0cbf701c61
braney
  Tue May 25 17:31:38 2021 -0700
implement cart editing.  Needs doc.  ;-)

diff --git src/hg/lib/hdb.c src/hg/lib/hdb.c
index 8fa937a..b975b67 100644
--- src/hg/lib/hdb.c
+++ src/hg/lib/hdb.c
@@ -47,30 +47,37 @@
 #include "regexHelper.h"
 #include "filePath.h"
 #include "wikiLink.h"
 #include "cheapcgi.h"
 #include "chromAlias.h"
 
 
 #ifdef LOWELAB
 #define DEFAULT_PROTEINS "proteins060115"
 #define DEFAULT_GENOME "Pyrobaculum aerophilum"
 #else
 #define DEFAULT_PROTEINS "proteins"
 #define DEFAULT_GENOME "Human"
 #endif
 
+static unsigned trackDbCartVersion = 0;
+
+unsigned hdbGetTrackCartVersion()
+/* Get the cart version that our current trackDb wants to use. */
+{
+return trackDbCartVersion;
+}
 
 static struct sqlConnCache *hdbCc = NULL;  /* cache for primary database connection */
 static struct sqlConnCache *centralCc = NULL;
 static char *centralDb = NULL;
 static struct sqlConnCache *cartCc = NULL;  /* cache for cart; normally same as centralCc */
 static char *cartDb = NULL;
 static char *hdbTrackDb = NULL;
 
 /* cached list of tables in databases.  This keeps a hash of databases to
  * hashes of track/table name to slName list of actual table names, which
  * might be split.  Since individual tables can be mapped to different
  * profiles, and this information is only available when processing trackDb,
  * another table is kept to determine if these need to be checked.
  */
 static struct hash *tableList = NULL; // db to track to tables
@@ -3931,32 +3938,33 @@
 
 /* fill in supertrack fields, if any in settings */
 trackDbSuperMarkup(tdbList);
 trackDbAddTableField(tdbList);
 return tdbList;
 }
 
 boolean trackDataAccessibleHash(char *database, struct trackDb *tdb, struct hash *gbdbHash)
 /* Return TRUE if underlying data are accessible - meaning the track has either
  * a bigDataUrl with remote URL (http:// etc), a bigDataUrl with an existing local file,
  * or a database table with the same name.
  * Note: this returns FALSE for composite tracks; use this on subtracks or simple tracks. 
  *
  * if gbdbHash is not NULL, use it when looking for the file */
 {
-if (startsWith("mathWig", tdb->type))
+if (startsWith("mathWig", tdb->type) || startsWith("cartVersion", tdb->type)) 
     return TRUE; // assume mathWig data is available.  Fail at load time if it isn't
+    // cartVersion is a pseudo trackDb entry with no data
 char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
 if (bigDataUrl != NULL)
     {
     bigDataUrl = replaceChars(bigDataUrl, "$D", database);
     char *bigDataUrlLocal = hReplaceGbdb(bigDataUrl);
     if (hasProtocol(bigDataUrlLocal))
         return TRUE;
     else
         {
         if (gbdbHash == NULL)
             return fileExists(bigDataUrlLocal);
         else
             return hashLookup(gbdbHash, bigDataUrlLocal) != NULL;
         }
     }
@@ -4228,44 +4236,50 @@
         }
 
     hFreeConn(&conn);
 
     long now = clock1();
 
     // if the trackDb table has changed in the last five minutes, avoid caching because the table may
     // not be done changing.  Updates are not atomic.
     if (now - newestTime < 5 * 60)
         doCache = 0;
     else
         {
         struct trackDb *cacheTdb = trackDbCache(db, tdbPathString, newestTime);
 
         if (cacheTdb != NULL)
-            return cacheTdb;
+            {
+            if (sameString(cacheTdb->track, "cartVersion"))
+                trackDbCartVersion = -cacheTdb->priority;
+            return cacheTdb->next;
+            }
 
         memCheckPoint(); // we want to know how much memory is used to build the tdbList
         }
     }
 
 tdbList = loadTrackDb(db, NULL);
 tdbList = trackDbLinkUpGenerations(tdbList);
 tdbList = trackDbPolishAfterLinkup(tdbList, db);
 
 if (doCache)
     trackDbCloneTdbListToSharedMem(db, tdbPathString, tdbList, memCheckPoint());
 
-return tdbList;
+if (sameString(tdbList->track, "cartVersion"))
+    trackDbCartVersion = -tdbList->priority;
+return tdbList->next;
 }
 
 static struct trackDb *loadAndLookupTrackDb(struct sqlConnection *conn,
 					    char *where)
 /* Load trackDb object(s). Nothing done for composite tracks here. */
 {
 return loadTrackDb(sqlGetDatabase(conn), where);
 }
 
 static struct trackDb *loadTrackDbForTrack(struct sqlConnection *conn,
 					   char *track)
 /* Load trackDb object for a track. this is common code for two external
  * functions. Handle composite tracks and subtrack inheritance here.
  */
 {