a63596012d328a6333a06bdd640666dd336d065a chmalee Mon May 23 11:30:49 2022 -0700 Add a type line check to hubCheck, refs #28350, #13428 diff --git src/hg/utils/hubCheck/hubCheck.c src/hg/utils/hubCheck/hubCheck.c index 0454788..ebb2be8 100644 --- src/hg/utils/hubCheck/hubCheck.c +++ src/hg/utils/hubCheck/hubCheck.c @@ -749,30 +749,62 @@ (tdb->parent != NULL && (tdbIsComposite(tdb->parent) || tdbIsCompositeView(tdb->parent)))) { errAbort("Track \"%s\" is declared container multiWig and has parent \"%s\"." " Container multiWig tracks cannot be children of composites or views", tdb->track, tdb->parent->track); } } else if (tdb->subtracks != NULL) { errAbort("Track \"%s\" has children tracks (e.g: \"%s\"), but is not a " "compositeTrack, container, view or superTrack", tdb->track, tdb->subtracks->track); } } +boolean checkTypeLine(struct trackHubGenome *genome, struct trackDb *tdb, struct dyString *errors, struct trackHubCheckOptions *options) +{ +boolean retVal = FALSE; +struct errCatch *errCatch = errCatchNew(); +if (errCatchStart(errCatch)) + { + char *type = trackDbRequiredSetting(tdb, "type"); + char *splitType[4]; + int numWords = chopByWhite(cloneString(type), splitType, sizeof(splitType)); + if (sameString(splitType[0], "bigBed")) + { + if (numWords > 1 && (strchr(splitType[1], '+') || strchr(splitType[1], '.'))) + { + errAbort("error in type line \"%s\" for track \"%s\". " + "A space is needed after the \"+\" or \".\" character.", type, tdb->track); + } + if (numWords > 2 && (!sameString(splitType[2], "+") && !sameString(splitType[2], "."))) + { + errAbort("error in type line \"%s\" for track \"%s\". " + "Only \"+\" or \".\" is allowed after bigBed numFields setting.", type, tdb->track); + } + } + } +errCatchEnd(errCatch); +if (errCatch->gotError) + { + trackDbErr(errors, errCatch->message->string, genome, tdb, options->htmlOut); + retVal = TRUE; + } +return retVal; +} + int hubCheckTrack(struct trackHub *hub, struct trackHubGenome *genome, struct trackDb *tdb, struct trackHubCheckOptions *options, struct dyString *errors) /* Check track settings and optionally, files */ { int retVal = 0; int trackDbErrorCount = 0; if (options->checkSettings && options->settings) { //verbose(3, "Found %d settings to check to spec\n", slCount(settings)); verbose(3, "Checking track: %s\n", tdb->shortLabel); verbose(3, "Found %d settings to check to spec\n", hashNumEntries(tdb->settingsHash)); struct hashEl *hel; struct hashCookie cookie = hashFirst(tdb->settingsHash); while ((hel = hashNext(&cookie)) != NULL) @@ -815,32 +847,41 @@ if (options->htmlOut) { dyStringPrintf(errors, "trackData['%s'] = [", idName); } if (errCatchStart(errCatch)) { hubCheckParentsAndChildren(tdb); if (trackIsContainer) retVal |= hubCheckCompositeSettings(genome, tdb, errors, options); if (tdbIsSubtrack(tdb)) retVal |= hubCheckSubtrackSettings(genome, tdb, errors, options); - if (options->checkFiles) + // check that type line is syntactically correct regardless of + // if we actually want to check the data file itself + boolean foundTypeError = checkTypeLine(genome, tdb, errors, options); + + // No point in checking the data file if the type setting is incorrect, + // since hubCheckBigDataUrl will error out early with a less clear message + // if the type line is messed up. This has the added benefit of providing + // consistent messaging on command line interface vs web interface + if (!foundTypeError && options->checkFiles) hubCheckBigDataUrl(hub, genome, tdb); + if (!sameString(tdb->track, "cytoBandIdeo")) { trackHubAddDescription(genome->trackDbFile, tdb); if (!tdb->html) warn("warning: missing description page for track: '%s'", tdb->track); } } errCatchEnd(errCatch); if (errCatch->gotError || errCatch->gotWarning) { retVal = 1; trackDbErr(errors, errCatch->message->string, genome, tdb, options->htmlOut); if (errCatch->gotError) trackDbErrorCount += 1; }