2f73d7595b0e37b159e9c9355f8e99512bf37e81 max Wed Sep 10 08:33:03 2025 -0700 Merging Jim Robinsons code into the kent tree. Due to whitespace changes in his IDE, I'm merging this manually. The original code is at https://github.com/igvteam/ucsc_dev/. changes up to 48816bc are included. Also adding an API call to get the 2bit file and code to use it. diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c index 8dbe9f60891..77bb60992b8 100644 --- src/hg/hubApi/list.c +++ src/hg/hubApi/list.c @@ -710,109 +710,136 @@ jsonWriteObjectEnd(jw); } } } pipelineClose(&dataPipe); } errCatchEnd(errCatch); if (errCatch->gotError) { apiErrAbort(err400, err400Msg, "can not find genome='%s' for endpoint '/list/files'", db); } errCatchFree(&errCatch); return totalBytes; } -static void filesJsonOutput(FILE *f, char *genome, boolean textOut) +static void filesJsonOutput(FILE *f, char *genome, char *fileType, boolean textOut) /* for given genome, output the URLs to files available on hgdownload * can be a UCSC database genome, or a GenArk hub genome name */ { long long itemsReturned = 0; boolean genArkHub = FALSE; char genArkUrl[PATH_MAX + 1024]; if ( isGenArk(genome) ) { genArkHub = TRUE; safef(genArkUrl, sizeof(genArkUrl), "hubs/%s", genArkPath(genome)); } /* if UCSC genome database, it has already been proven to exist */ struct jsonWrite *jw = NULL; -if (textOut) +boolean doContext = (cgiInt(argSkipContext)==0); +if (textOut && doContext) { char outString[1024]; safef(outString, sizeof(outString), "# genome: %s", genome); textLineOut(outString); safef(outString, sizeof(outString), "# rsyncHost: rsync://%s", DOWNLOAD_HOST); textLineOut(outString); } else { jw = apiStartOutput(); + if (doContext) + { jsonWriteString(jw, "genome", genome); jsonWriteString(jw, "rsyncHost", "rsync://" DOWNLOAD_HOST); - + } jsonWriteListStart(jw, "urlList"); } long long totalBytes = 0; +if (fileType) + { + char outString[1024]; if (genArkHub) + { + safef(outString, sizeof(outString), "https://%s/%s/%s/%s.2bit", DOWNLOAD_HOST, genArkUrl, genome, genome); + textLineOut(outString); + } + else + { + safef(outString, sizeof(outString), "https://%s/gbdb/%s/%s.2bit", DOWNLOAD_HOST, genome, genome); + textLineOut(outString); + } + + } +else if (genArkHub) { totalBytes = rsyncList(jw, genome, genArkUrl, &itemsReturned, textOut); } else { totalBytes = rsyncList(jw, genome, "goldenPath", &itemsReturned, textOut); if (itemsReturned < maxItemsOutput) totalBytes += rsyncList(jw, genome, "gbdb", &itemsReturned, textOut); if (itemsReturned < maxItemsOutput) totalBytes += rsyncList(jw, genome, "mysql", &itemsReturned, textOut); } if (textOut) { char outString[1024]; + if (doContext) + { safef(outString, sizeof(outString), "# totalBytes: %lld", totalBytes); textLineOut(outString); - if (itemsReturned > maxItemsOutput) + } + if ((itemsReturned > maxItemsOutput) && doContext) { safef(outString, sizeof(outString), "# maxItemLimit: TRUE"); textLineOut(outString); safef(outString, sizeof(outString), "# itemsReturned: %d", maxItemsOutput); textLineOut(outString); } else { + if (doContext) + { safef(outString, sizeof(outString), "# itemsReturned: %lld", itemsReturned); textLineOut(outString); } + } textFinishOutput(); } else { jsonWriteListEnd(jw); + if (doContext) + { jsonWriteNumber(jw, "totalBytes", totalBytes); if (itemsReturned > maxItemsOutput) { jsonWriteBoolean(jw, "maxItemsLimit", TRUE); jsonWriteNumber(jw, "itemsReturned", maxItemsOutput); } else jsonWriteNumber(jw, "itemsReturned", itemsReturned); + } apiFinishOutput(0, NULL, jw); } } static void chromInfoJsonOutput(FILE *f, char *db) /* for given db, if there is a track, list the chromosomes in that track, * for no track, simply list the chromosomes in the sequence */ { char *splitSqlTable = NULL; struct hTableInfo *tableInfo = NULL; char *chromName = NULL; char *table = cgiOptionalString("track"); char *bigDataUrl = NULL; struct trackDb *thisTrack = NULL; @@ -1235,33 +1262,34 @@ { schemaJsonOutput(stdout, db, track); return; } else { hubSchemaJsonOutput(stdout, hubUrl, genome, track); return; } } else if (sameWord("files", words[1])) { boolean textOut = FALSE; char *extraArgs = verifyLegalArgs(argListFiles); if (extraArgs) - apiErrAbort(err400, err400Msg, "extraneous arguments found for function /list/files '%s', only 'genome' and 'format' is allowed.", extraArgs); + apiErrAbort(err400, err400Msg, "extraneous arguments found for function /list/files '%s', only 'genome', 'fileType', 'skipContext' and 'format' are allowed.", extraArgs); char *genome = cgiOptionalString("genome"); char *format = cgiOptionalString("format"); + char *fileType = cgiOptionalString("fileType"); if (isEmpty(genome)) apiErrAbort(err400, err400Msg, "must supply a genome name for endpoint '/list/files' (a database name or GenArk genome name, e.g.: 'hg38' or 'GCA_021951015.1'"); if (isNotEmpty(format)) { if (sameWord("text", format)) textOut = TRUE; else apiErrAbort(err400, err400Msg, "only format=text allowed for endpoint '/list/files', found: format=%s", format); } - filesJsonOutput(stdout, genome, textOut); + filesJsonOutput(stdout, genome, fileType, textOut); } else apiErrAbort(err400, err400Msg, "do not recognize endpoint function: '/%s/%s'", words[0], words[1]); } /* void apiList(char *words[MAX_PATH_INFO]) */