049e50b2293ce5e9102eef9177a7cb88b49d7a10 chmalee Wed Mar 4 14:14:03 2026 -0800 Move chromosome:start-end parsing into it's own function in hgFind so we can call just that code from elsewhere. Add a defaultPosition check for assembly hub into hubCheck that verifies the requested chromosome exists for that assembly. Do not warn if the range is too large since we actually silently accept that anyways and clamp to the chromosome ends. refs #37126 diff --git src/hg/utils/hubCheck/hubCheck.c src/hg/utils/hubCheck/hubCheck.c index 72fe62e50c0..977dd1c2f00 100644 --- src/hg/utils/hubCheck/hubCheck.c +++ src/hg/utils/hubCheck/hubCheck.c @@ -7,30 +7,31 @@ #include "bigBed.h" #include "dystring.h" #include "errCatch.h" #include "hgBam.h" #include "htmshell.h" #include "htmlPage.h" #include "hui.h" #include "net.h" #include "options.h" #include "trackDb.h" #include "trackHub.h" #include "udc.h" #include "vcf.h" #include "bedTabix.h" #include "knetUdc.h" +#include "hgFind.h" #ifdef USE_HAL #include "halBlockViz.h" #endif static int cacheTime = 1; void usage() /* Explain usage and exit. */ { errAbort( "hubCheck - Check a track data hub for integrity.\n" "usage:\n" " hubCheck http://yourHost/yourDir/hub.txt\n" "options:\n" @@ -1070,41 +1071,55 @@ struct errCatch *errCatch = errCatchNew(); struct trackDb *tdbList = NULL; int genomeErrorCount = 0; boolean openedGenome = FALSE; verbose(3, "checking genome %s\n", trackHubSkipHubName(genome->name)); if (errCatchStart(errCatch)) { if (genome->twoBitPath != NULL) { // check that twoBitPath is a valid file, warn instead of errAbort so we can continue checking // the genome stanza char *twoBit = genome->twoBitPath; if (!extFileExists(twoBit)) warn("Error: '%s' twoBitPath does not exist or is not accessible: '%s'", genome->name, twoBit); + else + { + // verify that the defaultPos references an actual chromosome and valid range for that chromosome + char *inpPos = cloneString(genome->defaultPos); + int relStart = 0, relEnd = 0; + boolean relativeFlag = FALSE, singleBaseSpec = FALSE; + if (!parseAndResolvePosition(&inpPos, genome->name, NULL, &relStart, &relEnd, &relativeFlag, &singleBaseSpec)) + { + // again use a warn so we can continue checking other genome stanza settings that do not + // rely on the 2bit file + warn("Error: '%s' defaultPos '%s' does not reference a valid chromosome in the 2bit file: '%s'", trackHubSkipHubName(genome->name), genome->defaultPos, twoBit); + } + } // groups and htmlPath are optional settings, again only warn if they are malformed char *groupsFile = genome->groups; if (groupsFile != NULL && !extFileExists(groupsFile)) warn("warning: '%s' groups file does not exist or is not accessible: '%s'", genome->name, groupsFile); char *htmlPath = hashFindVal(genome->settingsHash, "htmlPath"); if (htmlPath == NULL) warn("warning: missing htmlPath setting for assembly hub '%s'", genome->name); else if (!extFileExists(htmlPath)) warn("warning: '%s' htmlPath file does not exist or is not accessible: '%s'", genome->name, htmlPath); + } boolean foundFirstGenome = FALSE; tdbList = trackHubTracksForGenome(hub, genome, NULL, &foundFirstGenome); tdbList = trackDbLinkUpGenerations(tdbList); tdbList = trackDbPolishAfterLinkup(tdbList, genome->name); trackHubPolishTrackNames(hub, tdbList); } errCatchEnd(errCatch); if (errCatch->gotError || errCatch->gotWarning) { openedGenome = TRUE; genomeErr(errors, errCatch->message->string, hub, genome, options->htmlOut); if (errCatch->gotError || !options->allowWarnings) genomeErrorCount += 1; }