2ea6e837990eb39bc317f2b1aacacfe4ff77a7ce
hiram
  Tue Jun 11 18:00:29 2024 -0700
correctly check boolean CGI variable and ouput the tracks in a single file track hub while in html mode no redmine

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index 95f479c..af5d541 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -384,30 +384,31 @@
  *   name of largest chrom and its size
  */
 {
 int retVal = 0;
 *chromCount = 0;
 *itemCount = 0;
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     if (startsWithWord("bigNarrowPeak", type)
             || startsWithWord("bigBed", type)
             || startsWithWord("bigGenePred", type)
             || startsWithWord("bigPsl", type)
             || startsWithWord("bigChain", type)
             || startsWithWord("bigMaf", type)
+            || startsWithWord("bigRmsk", type)
             || startsWithWord("bigBarChart", type)
             || startsWithWord("bigInteract", type))
         {
         struct bbiFile *bbi = NULL;
         bbi = bigBedFileOpen(bigDataUrl);
         struct bbiChromInfo *chromList = bbiChromList(bbi);
         *chromCount = slCount(chromList);
         *itemCount = bigBedItemCount(bbi);
         bbiLargestChrom(chromList, chromName, chromSize);
         bbiChromInfoFreeList(&chromList);
         bbiFileClose(&bbi);
         }
     else if (startsWithWord("bigWig", type))
         {
         struct bbiFile *bwf = bigWigFileOpen(bigDataUrl);
@@ -471,31 +472,31 @@
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     {
     retVal = 1;
     dyStringPrintf(errors, "%s", errCatch->message->string);
     }
 errCatchFree(&errCatch);
 
 return retVal;
 }	/* static int bbiBriefMeasure() */
 
 static void hubSubTracks(struct trackHub *hub, char *db, struct trackDb *tdb,
     struct hash *countTracks,  long chromCount, long itemCount,
     char *chromName, unsigned chromSize, char *genome, char *errorString)
-/* tdb has subtracks, show only subTracks, no details */
+/* tdb has subtracks, show only subTracks, no details, this is RECURSIVE */
 {
 hPrintf("    <li><ul>\n");
 if (debug)
     {
     hPrintf("    <li>subtracks for '%s' db: '%s'</li>\n", tdb->track, db);
     hPrintf("    <li>chrom: '%s' size: %u</li>\n", chromName, chromSize);
     }
 if (tdb->subtracks)
     {
     struct trackDb *tdbEl = NULL;
     for (tdbEl = tdb->subtracks; tdbEl; tdbEl = tdbEl->next)
 	{
 	boolean compositeContainer = tdbIsComposite(tdbEl);
 	boolean compositeView = tdbIsCompositeView(tdbEl);
 	if (! (compositeContainer || compositeView) )
@@ -572,30 +573,31 @@
     if (sameWord("tableBrowser", hel->name)
 		&& startsWithWord("off", (char*)hel->val))
 	hPrintf("    <li><b>protectedData</b>: 'true'</li>\n");
     else if (protectedData && sameWord("bigDataUrl", hel->name))
 	hPrintf("    <li><b>bigDataUrl</b>: &lt;protected data&gt;</li>\n");
     else if (isEmpty((char *)hel->val))
 	hPrintf("    <li><b>%s</b>: &lt;empty&gt;</li>\n", hel->name);
     else
 	hPrintf("    <li><b>%s</b>: '%s'</li>\n", hel->name, (char *)hel->val);
     }
 if (tdb->subtracks)
     {
     struct trackDb *tdbEl = NULL;
     if (debug)
 	hPrintf("   <li>has %d subtrack(s)</li>\n", slCount(tdb->subtracks));
+
     for (tdbEl = tdb->subtracks; tdbEl; tdbEl = tdbEl->next)
 	{
         hPrintf("<li>subtrack: %s of parent: %s : type: '%s' (TBD: sample data)</li>\n", tdbEl->track, tdbEl->parent->track, tdbEl->type);
 	hashCountTrack(tdbEl, countTracks);
 	trackSettings(db, tdbEl, countTracks);
 	}
     }
 hPrintf("    </ul></li>\n");
 }
 
 static void hubCountOneTdb(struct trackHub *hub, char *db, struct trackDb *tdb,
     char *bigDataIndex, struct hash *countTracks, char *chromName,
     unsigned chromSize, char *genome)
 {
 char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
@@ -820,33 +822,31 @@
 
 hPrintf("    <li><ul>\n");
 struct hashEl *hel;
 struct hashCookie hc = hashFirst(genome->settingsHash);
 while ((hel = hashNext(&hc)) != NULL)
     {
     if (sameWord("description", hel->name) ||
 	sameWord("defaultPos", hel->name) ||
 	sameWord("organism", hel->name) ||
 	sameWord("groups", hel->name) ||
 	sameWord("twoBitPath", hel->name) ||
 	sameWord("genome", hel->name)
 	)
 	continue;	// already output in header
     if (sameWord("trackDb", hel->name))	/* examine the trackDb structure */
-	{
 	hubTrackList(hub, tdb, genome);
-        }
     else
 	hPrintf("    <li><b>%s</b>: %s</li>\n", hel->name, (char *)hel->val);
     if (timeOutReached())
 	break;
     }
 hPrintf("    </ul></li>\n");
 }
 
 static unsigned largestChromInfo(struct chromInfo *ci, char **chromName)
 /* find largest chrom in this chromInfo, return name and size */
 {
 unsigned size = 0;
 char *name = NULL;
 struct chromInfo *el;
 for (el = ci; el; el = el->next)
@@ -904,30 +904,32 @@
 	char sizeString[64];
 	sprintLongWithCommas(sizeString, chromSize);
 	hPrintf("<li><b>Sequence count</b> %d, <b>largest</b>: %s at %s bases</li>\n", slCount(ci), chromName, sizeString);
        safef(urlReference, sizeof(urlReference), " <a href='%s/getData/sequence?hubUrl=%s;genome=%s;chrom=%s;start=%u;end=%u' target=_blank>JSON example sequence output: %s:%u-%u</a>", urlPrefix, hubTop->url, genome->name, chromName, chromSize/4, (chromSize/4)+128, chromName, chromSize/4, (chromSize/4)+128);
         hPrintf("<li>%s</li>\n", urlReference);
 	}
     safef(urlReference, sizeof(urlReference), " <a href='%s/list/tracks?hubUrl=%s;genome=%s%s' target=_blank>JSON example list tracks output</a>", urlPrefix, hubTop->url, genome->name, trackLeavesOnly ? ";trackLeavesOnly=1" : "");
     hPrintf("<li>%s</li>\n", urlReference);
     hubInfo("organism", genome->organism);
     hubInfo("name", genome->name);
     hubInfo("description", genome->description);
     hubInfo("groups", genome->groups);
     hubInfo("defaultPos", genome->defaultPos);
     hubInfo("trackDbFile", genome->trackDbFile);
     hubAssemblySettings(hubTop, genome);
+    struct trackDb *tdbList = obtainTdb(genome, NULL);
+    hubTrackList(hubTop, tdbList, genome);
     if (measureTiming)
 	{
 	long thisTime = clock1000();
 	hPrintf("<li><em>processing time %s: %ld millis</em></li>\n", genome->name, thisTime - lastTime);
 	hPrintf("<hr>\n");
         }
     if (timeOutReached())
 	break;
     }
 if (trackCounter->elCount)
     {
     hPrintf("    <li>total genome assembly count: %ld</li>\n", totalAssemblyCount);
     hPrintf("    <li>%ld total tracks counted, %d different track types:</li>\n", totalTracks, trackCounter->elCount);
     hPrintf("    <li><ul>\n");
     struct hashEl *hel, *helList = hashElListHash(trackCounter);
@@ -1397,30 +1399,32 @@
 
 char *otherHubUrl = cartUsualString(cart, "urlHub", "");
 char *hubDropDown = cartUsualString(cart, "publicHubs", defaultHub);
 char *urlDropDown = urlFromShortLabel(hubDropDown);
 char *ucscDb = cartUsualString(cart, "ucscGenome", defaultDb);
 char *selectRadio = cartUsualString(cart, RADIO_GROUP, RADIO_PUBHUB);
 char *urlInput = urlDropDown;	/* assume public hub */
 if (debug)
     {
     hPrintf("<ul>\n");
     hPrintf("<li>otherHubUrl: '%s'</li>\n", otherHubUrl);
     hPrintf("<li>hubDropDown: '%s'</li>\n", hubDropDown);
     hPrintf("<li>urlDropDown: '%s'</li>\n", urlDropDown);
     hPrintf("<li>ucscDb: '%s'</li>\n", ucscDb);
     hPrintf("<li>urlInput: '%s'</li>\n", urlInput);
+    hPrintf("<li>trackLeavesOnly: '%s'</li>\n", trackLeavesOnly ? "TRUE" : "FALSE");
+    hPrintf("<li>jsonOutputArrays: '%s'</li>\n", jsonOutputArrays ? "TRUE" : "FALSE");
     hPrintf("</ul>\n");
     }
 if (isEmpty(otherHubUrl))
     otherHubUrl = urlInput;
 
 if (sameWord(RADIO_OTHERHUB, selectRadio))	/* requested other hub URL */
     urlInput = otherHubUrl;
 
 long lastTime = clock1000();
 struct trackHub *hub = errCatchTrackHubOpen(urlInput);
 if (measureTiming)
     {
     long thisTime = clock1000();
     hPrintf("<em>hub open time: %ld millis</em><br>\n", thisTime - lastTime);
     }
@@ -1486,42 +1490,42 @@
 for ( ; el; el = el->next)
     {
     hashIncInt(varCounter, el->name);
     }
 struct hashCookie cookie = hashFirst(varCounter);
 struct hashEl *hel = NULL;
 for ( hel = hashNext(&cookie); hel; hel = hashNext(&cookie))
     {
     if (ptToInt(hel->val) > 1)
 	apiErrAbort(err400, err400Msg, "parameter '%s' found %d times, only one instance allowed", hel->name, ptToInt(hel->val));
     }
 
 char *trackLeaves = cgiOptionalString("trackLeavesOnly");
 if (isNotEmpty(trackLeaves))
     {
-    if (sameString("1", trackLeaves))
+    if (SETTING_IS_ON(trackLeaves))
 	trackLeavesOnly = TRUE;
     else if (sameString("0", trackLeaves))
 	trackLeavesOnly = FALSE;
     else
 	apiErrAbort(err400, err400Msg, "unrecognized 'trackLeavesOnly=%s' argument, can only be =1 or =0", trackLeaves);
     }
 
 char *jsonArray = cgiOptionalString("jsonOutputArrays");
 if (isNotEmpty(jsonArray))
     {
-    if (sameString("1", jsonArray))
+    if (SETTING_IS_ON(jsonArray))
 	jsonOutputArrays = TRUE;
     else if (sameString("0", jsonArray))
 	jsonOutputArrays = FALSE;
     else
 	apiErrAbort(err400, err400Msg, "unrecognized 'jsonOutputArrays=%s' argument, can only be =1 or =0", jsonArray);
     }
 
 int maybeDebug = cgiOptionalInt("debug", 0);
 if (1 == maybeDebug)
     debug = TRUE;
 
 char *measTime = cgiOptionalString("measureTiming");
 if (isNotEmpty(measTime) && sameWord("1", measTime))
     measureTiming = TRUE;
 char *maxOut = cgiOptionalString("maxItemsOutput");