db90d1cfebedc95cfc8e5f394b0f5863a7e50008 kate Wed May 13 16:14:27 2015 -0700 1. Change level-alpha to level-new (input from group review). Add -settings option to hubCheck (doesn't check, just shows settings and level). Add level to all settings (very initial proposed set based on input from Ensembl). refs #10015 diff --git src/hg/lib/trackHubCheck.c src/hg/lib/trackHubCheck.c index 6fca442..03c35be 100644 --- src/hg/lib/trackHubCheck.c +++ src/hg/lib/trackHubCheck.c @@ -178,96 +178,142 @@ } verbose(2, "%d tracks in %s\n", slCount(tdbList), genome->name); return retVal; } char *trackHubVersionDefault() /* Return current version of trackDb settings spec for hubs */ { // TODO: get from goldenPath/help/trackDb/trackDbHub.current.html return "v1"; // minor rev to v1a, etc. } +int trackHubSettingLevel(struct trackHubSetting *spec) +/* Get integer for level (core > full > new > deprecated) */ +{ +if (sameString(spec->level, "core")) + return 4; +if (sameString(spec->level, "full")) + return 3; +if (sameString(spec->level, "new")) + return 2; +if (sameString(spec->level, "deprecated")) + return 1; +return 0; // errAbort ? +} + + +boolean trackHubSettingLevelCmp(struct trackHubSetting *spec1, struct trackHubSetting *spec2) +{ +/* Compare setting levels */ +return trackHubSettingLevel(spec1) - trackHubSettingLevel(spec2); +} + + struct trackHubSetting *trackHubSettingsForVersion(char *version) /* Return list of settings with support level. Version can be version string or spec url */ { if (version == NULL) version = trackHubVersionDefault(); char *specUrl; if (startsWith("http", version)) specUrl = version; else { char buf[256]; - safef(buf, sizeof buf, "http://genome.ucsc.edu/goldenPath/help/trackDb/trackDbHub.%s.html", + // TODO: local host + safef(buf, sizeof buf, "http://hgwdev-kate.cse.ucsc.edu/goldenPath/help/trackDb/trackDbHub.%s.html", version); specUrl = buf; } struct htmlPage *page = htmlPageGet(specUrl); if (page == NULL) errAbort("Can't open trackDb settings spec %s\n", specUrl); +// TODO: check return status -- this succeeds even for 404's ? verbose(3, "Opened URL %s\n", specUrl); /* Retrieve specs from file url. - * Settings are the first text word within a <code> element nested in * a <div> having + * Settings are the first text word within any <code> element nested in * a <div> having * attribute class="format". The support level ('level-*') is the class value of the * <code> tag. * E.g. <div class="format"><code class="level-core">boxedConfig on</code></div> produces: * setting=boxedConfig, class=core */ struct htmlTag *tag, *codeTag; struct htmlAttribute *attr, *codeAttr; -struct trackHubSetting *spec, *specs = NULL; +struct trackHubSetting *spec, *savedSpec; +struct hash *specHash = hashNew(0); verbose(3, "Found %d tags\n", slCount(page->tags)); int divCount = 0; char buf[256]; for (tag = page->tags; tag != NULL; tag = tag->next) { - if (differentWord(tag->name, "div")) + verbose(6, " TAG: %s\n", tag->name); + if (differentWord(tag->name, "DIV")) continue; divCount++; - verbose(5, "<div>%s\n", tag->start); - for (attr = tag->attributes; attr != NULL; attr = attr->next) - { + attr = tag->attributes; if (differentWord(attr->name, "class") || differentWord(attr->val, "format")) continue; - // TODO: Look on code tags (there may be multiple after "format" - codeTag = tag->next; - verbose(5, "Found format: tag %s\n", tag->name); - if (differentWord(codeTag->name, "CODE")) - break; - verbose(4, "Found <code>\n"); - for (codeAttr = codeTag->attributes; codeAttr != NULL; codeAttr = codeAttr->next) + verbose(7, "Found format: tag %s\n", tag->name); + // Look for one or more <code> tags in this format div + for (codeTag = tag->next; + codeTag != NULL && differentWord(codeTag->name,"/DIV"); codeTag = codeTag->next) { - verbose(5, "attr: name=%s, val=%s\n", codeAttr->name, codeAttr->val); - if (differentWord(codeAttr->name, "class") || !startsWith("level-", codeAttr->val)) - break; + if (differentWord(codeTag->name, "CODE")) + continue; + verbose(7, "Found <code>\n"); + codeAttr = codeTag->attributes; + //verbose(8, "attr: name=%s, val=%s\n", codeAttr->name, codeAttr->val); + if (codeAttr == NULL || differentString(codeAttr->name, "class") || + !startsWith("level-", codeAttr->val)) + continue; AllocVar(spec); int len = min(codeTag->next->start - codeTag->end, sizeof buf - 1); memcpy(buf, codeTag->end, len); buf[len] = 0; + verbose(7, "Found spec: %s\n", buf); spec->name = cloneString(firstWordInLine(buf)); - spec->level = chopPrefixAt(cloneString(codeAttr->val), '-'); - // TODO: hash to pickup dupes (retain one with level, warn if multiple differ) - slAddHead(&specs, spec); - verbose(4, "spec: name=%s, level=%s\n", spec->name, spec->level); + spec->level = cloneString(chopPrefixAt(codeAttr->val, '-')); + verbose(6, "spec: name=%s, level=%s\n", spec->name, spec->level); + + savedSpec = (struct trackHubSetting *)hashFindVal(specHash, spec->name); + if (savedSpec != NULL) + verbose(6, "found spec %s level %s in hash\n", savedSpec->name, savedSpec->level); + if (savedSpec == NULL) + { + hashAdd(specHash, spec->name, spec); + verbose(6, "added spec %s at level %s\n", spec->name, spec->level); + } + else if (trackHubSettingLevelCmp(spec, savedSpec) > 0) + { + hashReplace(specHash, spec->name, spec); + verbose(6, "replaced spec %s at level %s, was %s\n", + spec->name, spec->level, savedSpec->level); } } } verbose(5, "Found %d <div>'s\n", divCount); +struct hashEl *el, *list = hashElListHash(specHash); +verbose(5, "Found %d settings's\n", slCount(list)); +slSort(&list, hashElCmp); +struct trackHubSetting *specs = NULL; +for (el = list; el != NULL; el = el->next) + slAddHead(&specs, el->val); +slReverse(&specs); return specs; } int trackHubCheck(char *hubUrl, struct trackHubCheckOptions *options, struct dyString *errors) /* hubCheck - Check a track data hub for integrity. Put errors in dyString. * return 0 if hub has no errors, 1 otherwise * if options->checkTracks is TRUE, check remote files of individual tracks */ { struct errCatch *errCatch = errCatchNew(); struct trackHub *hub = NULL; int retVal = 0; if (errCatchStart(errCatch))