bf7b450d396d8fe15d5198d3e4a55d8ac864e6b3
hiram
  Mon Jan 28 14:55:21 2019 -0800
now output genome list for any hub refs #18869

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index 1122600..ef705a8 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -432,44 +432,48 @@
 struct hashCookie hc = hashFirst(genome->settingsHash);
 while ((hel = hashNext(&hc)) != NULL)
     {
     hPrintf("    <li>%s : %s</li>\n", hel->name, (char *)hel->val);
     if (sameWord("trackDb", hel->name))	/* examine the trackDb structure */
 	{
         struct trackDb *tdb = trackHubTracksForGenome(genome->trackHub, genome);
 	trackList(tdb, genome);
         }
     if (timeOutReached())
 	break;
     }
 hPrintf("    </ul>\n");
 }
 
-static void genomeList (struct trackHub *hubTop)
+static struct slName *genomeList(struct trackHub *hubTop)
 /* follow the pointers from the trackHub to trackHubGenome and around
  * in a circle from one to the other to find all hub resources
  */
 {
+struct slName *retList = NULL;
+
 long totalAssemblyCount = 0;
 struct trackHubGenome *genome = hubTop->genomeList;
 
 hPrintf("<h4>genome sequences (and tracks) present in this track hub</h4>\n");
 hPrintf("<ul>\n");
 long lastTime = clock1000();
 for ( ; genome; genome = genome->next )
     {
     ++totalAssemblyCount;
+    struct slName *el = slNameNew(genome->name);
+    slAddHead(&retList, el);
     if (genome->organism)
 	{
 	hPrintf("<li>%s - %s - %s</li>\n", genome->organism, genome->name, genome->description);
 	}
     else
 	{	/* can there be a description when organism is empty ? */
 	hPrintf("<li>%s</li>\n", genome->name);
 	}
     if (genome->settingsHash)
 	assemblySettings(genome);
     if (measureTiming)
 	{
 	long thisTime = clock1000();
 	hPrintf("<em>processing time %s: %ld millis</em><br>\n", genome->name, thisTime - lastTime);
 	}
@@ -478,95 +482,116 @@
     }
 if (trackCounter->elCount)
     {
     hPrintf("    <li>total assembly count: %ld</li>\n", totalAssemblyCount);
     hPrintf("    <li>%ld total tracks counted, %d different track types:</li>\n", totalTracks, trackCounter->elCount);
     hPrintf("    <ul>\n");
     struct hashEl *hel;
     struct hashCookie hc = hashFirst(trackCounter);
     while ((hel = hashNext(&hc)) != NULL)
 	{
 	hPrintf("    <li>%d - %s - total</li>\n", ptToInt(hel->val), hel->name);
 	}
     hPrintf("    </ul>\n");
     }
 hPrintf("</ul>\n");
-}
+return retList;
+}	/*	static struct slName *genomeList (struct trackHub *hubTop) */
 
 static char *urlFromShortLabel(char *shortLabel)
 {
 char hubUrl[1024];
 char query[1024];
 struct sqlConnection *conn = hConnectCentral();
 // Build a query to select the hubUrl for the given shortLabel
 sqlSafef(query, sizeof(query), "select hubUrl from %s where shortLabel='%s'",
       hubPublicTableName(), shortLabel);
 if (! sqlQuickQuery(conn, query, hubUrl, sizeof(hubUrl)))
     hubUrl[0] = 0;
 hDisconnectCentral(&conn);
 return cloneString(hubUrl);
 }
 
 static void jsonPublicHubs()
 {
 struct hubPublic *el = publicHubList;
-hPrintf("{\"publicHubs\":[");
+printf("{\"publicHubs\":[");
 for ( ; el != NULL; el = el->next )
     {
     hubPublicJsonOutput(el, stdout);
     if (el->next)
-       hPrintf(",");
+       printf(",");
     }
-hPrintf("]}\n");
+printf("]}\n");
 }
 
 #define MAX_PATH_INFO 32
 static void apiList(char *words[MAX_PATH_INFO])
 /* 'list' function */
 {
 if (sameWord("publicHubs", words[1]))
     jsonPublicHubs();
 else if (sameWord("genomes", words[1]))
     {
     char *hubUrl = cgiOptionalString("hubUrl");
     if (isNotEmpty(hubUrl))
 	{
-        hPrintf("# list genomes for hubUrl: '%s'\n", hubUrl);
+        struct trackHub *hub = trackHubOpen(hubUrl, "");
+        if (hub->genomeList)
+	    {
+            fputc('{',stdout);
+            jsonString(stdout, "hubUrl", hubUrl);
+            fputc(',',stdout);
+            printf("\"genomes\":[");
+	    struct slName *theList = genomeList(hub);
+            slNameSort(&theList);
+            struct slName *el = theList;
+            for ( ; el ; el = el->next )
+		{
+		char *n = jsonEscape(el->name);
+                printf("\"%s\"", n);
+		if (el->next)
+		    fputc(',',stdout);
+		}
+            printf("]}\n");
+	    }
 	}
     else
 	errAbort("# must supply hubUrl='http:...' some URL to a hub for /list/genomes\n");
     }
 else
     errAbort("# ERROR: do not recognize '%s' for 'list' function\n", words[1]);
 }
 
 static struct hash *apiFunctionHash = NULL;
 
 static void setupFunctionHash()
 {
 if (apiFunctionHash)
     return;
 
 apiFunctionHash = hashNew(0);
 hashAdd(apiFunctionHash, "list", &apiList);
 }
 
 static void apiFunctionSwitch(char *pathInfo)
 /* given a pathInfo string: /command/subCommand/etc...
  *  parse that and decide on which function to acll
  */
 {
+hPrintDisable();	/* turn off all normal HTML output */
+
 /* the leading slash has been removed from the pathInfo, therefore, the
  * chop will have the first word in words[0]
  */
 char *words[MAX_PATH_INFO];/*expect no more than MAX_PATH_INFO number of words*/
 int wordCount = chopByChar(pathInfo, '/', words, ArraySize(words));
 if (wordCount < 2)
     errAbort("ERROR: no commands found in path info\n");
 
 void (*apiFunction)(char **) = hashMustFindVal(apiFunctionHash, words[0]);
 
 (*apiFunction)(words);
 
 }
 
 static void doMiddle(struct cart *theCart)
@@ -660,31 +685,31 @@
 hPrintf("\n&nbsp;&nbsp;");
 allTrackSettings = cartUsualBoolean(cart, "allTrackSettings", FALSE);
 hCheckBox("allTrackSettings", allTrackSettings);
 hPrintf("&nbsp;display all track settings for each track : %s<br>\n", allTrackSettings ? "TRUE" : "FALSE");
 
 
 hPrintf("<br>\n</form>\n");
 
 hPrintf("<p>URL: %s - %s<br>\n", urlInput, sameWord("go",goPublicHub) ? "public hub" : "other hub");
 hPrintf("name: %s<br>\n", hub->shortLabel);
 hPrintf("description: %s<br>\n", hub->longLabel);
 hPrintf("default db: '%s'<br>\n", isEmpty(hub->defaultDb) ? "(none available)" : hub->defaultDb);
 printf("docRoot:'%s'<br>\n", docRoot);
 
 if (hub->genomeList)
-    genomeList(hub);
+    (void) genomeList(hub);	/* ignore returned list */
 
 hPrintf("</p>\n");
 
 if (timedOut)
     hPrintf("<h1>Reached time out %ld seconds</h1>", timeOutSeconds);
 if (measureTiming)
     hPrintf("<em>Overall total time: %ld millis</em><br>\n", clock1000() - enteredMainTime);
 
 cartWebEnd();
 }	/*	void doMiddle(struct cart *theCart)	*/
 
 /* Null terminated list of CGI Variables we don't want to save
  * permanently. */
 char *excludeVars[] = {"Submit", "submit", NULL,};