0f043ee1a1ebdbc699bddb5c3f6ec00539976672
angie
  Thu Aug 20 13:34:01 2015 -0700
Wrapping an errCatch around cartTrackDbInit so that if we switch to
some database on hgwdev that is in dbDb but doesn't have a trackDb,
we can return an empty groupedTrackDb instead of causing a JSON parse
error.

diff --git src/hg/lib/cartJson.c src/hg/lib/cartJson.c
index 2f9a074..cee8715 100644
--- src/hg/lib/cartJson.c
+++ src/hg/lib/cartJson.c
@@ -1,20 +1,21 @@
 /* cartJson - parse and execute JSON commands to update cart and/or return cart data as JSON. */
 #include "common.h"
 #include "cartJson.h"
 #include "cartTrackDb.h"
 #include "cheapcgi.h"
+#include "errCatch.h"
 #include "grp.h"
 #include "hdb.h"
 #include "hgFind.h"
 #include "htmshell.h"
 #include "hubConnect.h"
 #include "hui.h"
 #include "jsonParse.h"
 #include "obscure.h"
 #include "regexHelper.h"
 #include "suggest.h"
 #include "trackDb.h"
 #include "trackHub.h"
 #include "web.h"
 
 char *cartJsonOptionalParam(struct hash *paramHash, char *name)
@@ -498,45 +499,61 @@
     // Group has at least one track, so append it to jw.
     jsonWriteListEnd(jwNew);
     jsonWriteObjectEnd(jwNew);
     jsonWriteAppend(jw, NULL, jwNew);
     }
 jsonWriteFree(&jwNew);
 return gotSomething;
 }
 
 void cartJsonGetGroupedTrackDb(struct cartJson *cj, struct hash *paramHash)
 /* Translate trackDb list (only a subset of the fields) into JSON array of track group objects;
  * each group contains an array of track objects that may have subtracks.  Send it in a wrapper
  * object that includes the database from which it was taken; it's possible that by the time
  * this reaches the client, the user might have switched to a new db. */
 {
+struct jsonWrite *jw = cj->jw;
 struct trackDb *fullTrackList = NULL;
 struct grp *fullGroupList = NULL;
+struct errCatch *errCatch = errCatchNew();
+if (errCatchStart(errCatch))
+    {
     cartTrackDbInit(cj->cart, &fullTrackList, &fullGroupList, /* useAccessControl=*/TRUE);
+    }
+errCatchEnd(errCatch);
+if (errCatch->gotError)
+    {
+    warn("%s", errCatch->message->string);
+    jsonWriteObjectStart(jw, "groupedTrackDb");
+    jsonWriteString(jw, "db", cartString(cj->cart, "db"));
+    jsonWriteListStart(jw, "groupedTrackDb");
+    jsonWriteListEnd(jw);
+    jsonWriteObjectEnd(jw);
+    return;
+    }
+errCatchFree(&errCatch);
 struct hash *groupedTrackRefList = hashTracksByGroup(fullTrackList);
 // If the optional param 'fields' is given, hash the field names that should be returned.
 char *fields = cartJsonOptionalParam(paramHash, "fields");
 struct hash *fieldHash = hashFromCommaString(fields);
 char *excludeTypes = cartJsonOptionalParam(paramHash, "excludeTypes");
 struct hash *excludeTypesHash = hashFromCommaString(excludeTypes);
 // Also check for optional parameter 'maxDepth':
 int maxDepth = -1;
 char *maxDepthStr = cartJsonOptionalParam(paramHash, "maxDepth");
 if (isNotEmpty(maxDepthStr))
     maxDepth = atoi(maxDepthStr);
-struct jsonWrite *jw = cj->jw;
 jsonWriteObjectStart(jw, "groupedTrackDb");
 jsonWriteString(jw, "db", cartString(cj->cart, "db"));
 jsonWriteListStart(jw, "groupedTrackDb");
 int nonEmptyGroupCount = 0;
 struct grp *grp;
 for (grp = fullGroupList;  grp != NULL;  grp = grp->next)
     {
     struct slRef *tdbRefList = hashFindVal(groupedTrackRefList, grp->name);
     if (writeGroupedTrack(jw, grp->name, grp->label, fieldHash, excludeTypesHash,
                           maxDepth, tdbRefList))
         {
         nonEmptyGroupCount++;
         }
     }
 if (nonEmptyGroupCount == 0)