4409063550e6c4cc87cfd37f92f7b8db2699f885
hiram
  Fri Mar 13 17:13:14 2026 -0700
with the aid of claude add a genome argument to the ucscGenomes endpoint and manage assembly alias a bit more than previously for ucscGenomes and genarkGenomes refs #35972

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index c4d61549338..cb60ecf8e3f 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -1,20 +1,21 @@
 /* hubApi - access mechanism to hub data resources. */
 #include "dataApi.h"
 #include "botDelay.h"
 #include "jsHelper.h"
 #include "srcVersion.h"
+#include "asmAlias.h"
 /* can not include bamFile.h with the liftOver business, there
  * is a conflict in a definition of the enum 'bed'
  */
 #include "bamFile.h"
 
 /*
 +------------------+------------------+------+-----+---------+-------+
 | Field            | Type             | Null | Key | Default | Extra |
 +------------------+------------------+------+-----+---------+-------+
 | hubUrl           | longblob         | NO   | PRI | NULL    |       |
 | shortLabel       | varchar(255)     | NO   |     | NULL    |       |
 | longLabel        | varchar(255)     | NO   |     | NULL    |       |
 | registrationTime | varchar(255)     | NO   |     | NULL    |       |
 | dbCount          | int(10) unsigned | NO   |     | NULL    |       |
 | dbList           | blob             | YES  |     | NULL    |       |
@@ -35,31 +36,31 @@
 
 /* default is to list all trackDb entries, composite containers too.
  * This option will limit to only the actual track entries with data
  */
 boolean trackLeavesOnly = FALSE;  /* set by CGI parameter 'trackLeavesOnly' */
 /* this selects output type 'arrays', where the default type is: objects */
 boolean jsonOutputArrays = FALSE; /* set by CGI parameter 'jsonOutputArrays' */
 
 boolean measureTiming = FALSE;	/* set by CGI parameters */
 
 /* downloadUrl for use in error exits when reachedMaxItems */
 struct dyString *downloadUrl = NULL;
 
 /* valid argument listings to verify extraneous arguments */
 char *argListPublicHubs[] = { NULL };
-char *argListUcscGenomes[] = { NULL };
+char *argListUcscGenomes[] = { argGenome, NULL };
 char *argListGenarkGenomes[] = { argMaxItemsOutput, argGenome, NULL };
 char *argListHubGenomes[] = { argHubUrl, NULL };
 char *argListTracks[] = { argGenome, argHubUrl, argTrackLeavesOnly, NULL };
 char *argListChromosomes[] = { argGenome, argHubUrl, argTrack, NULL };
 char *argListSchema[] = { argGenome, argHubUrl, argTrack, NULL };
 char *argListFiles[] = { argGenome, argMaxItemsOutput, argFormat, argSkipContext, argFileType, NULL };
 char *argGetDataTrack[] = { argGenome, argHubUrl, argTrack, argChrom, argStart, argEnd, argMaxItemsOutput, argJsonOutputArrays, NULL };
 char *argGetDataSequence[] = { argGenome, argHubUrl, argTrack, argChrom, argStart, argEnd, argRevComp, NULL };
 char *argSearch[] = {argSearchTerm, argGenome, argHubUrl, argCategories, NULL};
 char *argFindGenome[] = {argQ, argMaxItemsOutput, argJsonOutputArrays, argStatsOnly, argBrowser, argYear, argCategory, argStatus, argLevel, argLiftable, NULL};
 char *argLiftOver[] = {argFromGenome, argToGenome, argChrom, argStart, argEnd, argFilter, argMaxItemsOutput, NULL};
 char *argLiftRequest[] = {argFromGenome, argToGenome, argEmail, argComment, NULL};
 
 /* Global only to this one source file */
 static struct cart *cart;             /* CGI and other variables */
@@ -1297,31 +1298,52 @@
             // change up the arguments so it appears an assembly hub had been requested correctly
             db = trackHubSkipHubName(db);
             cgiVarSet("genome", db);
             hubUrl = hub->hubUrl;
             cgiVarSet("hubUrl", hubUrl);
             }
         }
     }
 
 if (isEmpty(hubUrl) && isNotEmpty(db))
     {
     if ( ! isGenArk(db) )
 	{
 	struct sqlConnection *conn = hAllocConnMaybe(db);
 	if (NULL == conn)
+	    {
+	    /* not found directly, try alias lookup before failing */
+	    char *origDb = db;
+	    char *aliasDb = asmAliasFind(db);
+	    if (differentString(aliasDb, db))
+		{
+		db = aliasDb;
+		cgiVarSet("genome", db);
+		cgiVarSet("genomeInput", origDb); /* preserve original for error messages */
+		/* re-validate with the resolved name */
+		if ( ! isGenArk(db) )
+		    {
+		    conn = hAllocConnMaybe(db);
+		    if (NULL == conn)
+			dyStringPrintf(errorMsg, "can not find genome='%s' for endpoint '%s'", origDb, pathInfo);
+		    else
+			hFreeConn(&conn);
+		    }
+		}
+	    else
 		dyStringPrintf(errorMsg, "can not find genome='%s' for endpoint '%s'", db, pathInfo);
+	    }
 	else
 	    hFreeConn(&conn);
 	}
     }
 if (isNotEmpty(start) || isNotEmpty(end))
     {
     long long llStart = -1;
     long long llEnd = -1;
     struct errCatch *errCatch = errCatchNew();
     if (errCatchStart(errCatch))
         {
         if (isNotEmpty(start))
             llStart = sqlLongLong(start);
         if (isNotEmpty(end))
             llEnd = sqlLongLong(end);