a7e5ec255bed61069a80919b5e5f48c850ee3c2c
markd
  Mon Mar 1 15:00:01 2021 -0800
added hubCheck -genome to support only checking one genome

diff --git src/hg/utils/hubCheck/hubCheck.c src/hg/utils/hubCheck/hubCheck.c
index 50d84d2..7259011 100644
--- src/hg/utils/hubCheck/hubCheck.c
+++ src/hg/utils/hubCheck/hubCheck.c
@@ -29,66 +29,69 @@
 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"
   "   -noTracks             - don't check remote files for tracks, just trackDb (faster)\n"
   "   -checkSettings        - check trackDb settings to spec\n"
   "   -version=[v?|url]     - version to validate settings against\n"
   "                                     (defaults to version in hub.txt, or current standard)\n"
   "   -extra=[file|url]     - accept settings in this file (or url)\n"
   "   -level=base|required  - reject settings below this support level\n"
   "   -settings             - just list settings with support level\n"
+  "   -genome=genome        - only check this genome\n"
   "   -udcDir=/dir/to/cache - place to put cache for remote bigBed/bigWigs.\n"
   "                                     Will create this directory if not existing\n"
   "   -printMeta            - print the metadata for each track\n"
   "   -cacheTime=N          - set cache refresh time in seconds, default %d\n"
   "   -verbose=2            - output verbosely\n"
   , cacheTime
   );
 }
 
 static struct optionSpec options[] = {
    {"version", OPTION_STRING},
    {"level", OPTION_STRING},
    {"extra", OPTION_STRING},
    {"noTracks", OPTION_BOOLEAN},
    {"settings", OPTION_BOOLEAN},
    {"checkSettings", OPTION_BOOLEAN},
+   {"genome", OPTION_STRING},
    {"test", OPTION_BOOLEAN},
    {"printMeta", OPTION_BOOLEAN},
    {"udcDir", OPTION_STRING},
    {"specHost", OPTION_STRING},
    {"cacheTime", OPTION_INT},
    // intentionally undocumented option for hgHubConnect
    {"htmlOut", OPTION_BOOLEAN},
    {NULL, 0},
 };
 
 struct trackHubCheckOptions
 /* How to check track hub */
     {
     boolean checkFiles;         /* check remote files exist and are correct type */
     boolean checkSettings;      /* check trackDb settings to spec */
     boolean printMeta;          /* print out the metadata for each track */
     char *version;              /* hub spec version to check */
     char *specHost;             /* server hosting hub spec */
     char *level;                /* check hub is valid to this support level */
     char *extraFile;            /* name of extra file/url with additional settings to accept */
+    char *genome;               /* only check this genome */
     /* intermediate data */
     struct hash *settings;      /* supported settings for this version */
     struct hash *extra;         /* additional trackDb settings to accept */
     struct slName *suggest;     /* list of supported settings for suggesting */
     /* hgHubConnect only */
     boolean htmlOut;            /* put special formatted text into the errors dyString */
     };
 
 struct trackHubSettingSpec
 /* Setting name and support level, from trackDbHub.html (the spec) */
     {
     struct trackHubSettingSpec *next;
     char *name;                 /* setting name */
     char *level;                /* support level (required, base, full, new, deprecated) */
     };
@@ -847,30 +850,31 @@
     dyStringPrintf(errors, "];\n");
     }
 
 return retVal;
 }
 
 
 int hubCheckGenome(struct trackHub *hub, struct trackHubGenome *genome,
                 struct trackHubCheckOptions *options, struct dyString *errors)
 /* Check out genome within hub. */
 {
 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);
 
         // 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);
@@ -927,30 +931,50 @@
         safef(name, sizeof(name), "%s_%s", trackHubSkipHubName(genome->name), trackHubSkipHubName(tdb->track));
         dyStringPrintf(errors, "%s", makeFolderObjectString(name, tdb->longLabel, genomeName, "TRACK", TRUE, tdbCheckVal ? TRUE : FALSE));
         if (tdb->next != NULL)
             dyStringPrintf(errors, ",");
         }
     }
 if (options->htmlOut)
     dyStringPrintf(errors, "];\n");
 
 dyStringPrintf(errors, "%s", tdbDyString->string);
 dyStringClear(tdbDyString);
 
 return genomeErrorCount;
 }
 
+void checkGenomeRestriction(struct trackHubCheckOptions *options, struct trackHub *hub)
+/* check the a genome restriction from the command line is a valid genome */
+{
+if (options->genome == NULL)
+    return;  // OK
+for (struct trackHubGenome *genome = hub->genomeList; genome != NULL; genome = genome->next)
+    {
+    if (sameString(trackHubSkipHubName(genome->name), options->genome))
+        return;  // OK
+    }
+errAbort("Genome %s not found in hub", options->genome);
+}
+
+boolean shouldCheckGenomes(struct trackHubCheckOptions *options, struct trackHubGenome *genome)
+/* should this genome be check based on command line restrictions */
+{
+return (options->genome == NULL) ||
+    sameString(trackHubSkipHubName(genome->name), options->genome);
+}
+
 
 int trackHubCheck(char *hubUrl, struct trackHubCheckOptions *options, struct dyString *errors)
 /* 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;
 struct dyString *hubErrors = dyStringNew(0);
 int retVal = 0;
 
 if (errCatchStart(errCatch))
     {
     hub = trackHubOpen(hubUrl, "");
@@ -991,47 +1015,50 @@
     // the genomes settings, which need to be children of the root '#' node.
     // Here we are at a fatal error so we can close the array and return
     if (options->htmlOut)
         dyStringPrintf(errors, "];\n%s", dyStringCannibalize(&hubErrors));
     else
         dyStringPrintf(errors, "%s", dyStringCannibalize(&hubErrors));
     return 1;
     }
 if (options->htmlOut && retVal != 1)
     dyStringPrintf(errors, "trackData['#'] = [");
 
 if (options->checkSettings)
     retVal |= hubSettingsCheckInit(hub, options, errors);
 
 struct trackHubGenome *genome;
-int numGenomeErrors = 0;
+checkGenomeRestriction(options, hub);
 char genomeTitleString[128];
 struct dyString *genomeErrors = dyStringNew(0);
 for (genome = hub->genomeList; genome != NULL; genome = genome->next)
     {
-    numGenomeErrors = hubCheckGenome(hub, genome, options, genomeErrors);
+    if (shouldCheckGenomes(options, genome))
+        {
+        int numGenomeErrors = hubCheckGenome(hub, genome, options, genomeErrors);
         if (options->htmlOut)
             {
             char *genomeName = trackHubSkipHubName(genome->name);
             safef(genomeTitleString, sizeof(genomeTitleString),
                   "%s (%d configuration error%s)", genomeName, numGenomeErrors,
                   numGenomeErrors == 1 ? "" : "s");
             dyStringPrintf(errors, "%s,", makeFolderObjectString(genomeName, genomeTitleString, "#",
                            "Click to open node", TRUE, numGenomeErrors > 0 ? TRUE : FALSE));
             }
         retVal |= numGenomeErrors;
         }
+    }
 if (options->htmlOut)
     {
     dyStringPrintf(errors, "];\n");
     }
 dyStringPrintf(errors, "%s", dyStringCannibalize(&hubErrors));
 dyStringPrintf(errors, "%s", dyStringCannibalize(&genomeErrors));
 trackHubClose(&hub);
 return retVal;
 }
 
 
 static void addExtras(char *extraFile, struct trackHubCheckOptions *checkOptions)
 /* Add settings from extra file (e.g. for specific hub display site) */
 {
 verbose(2, "Accepting extra settings in '%s'\n", extraFile);
@@ -1082,30 +1109,31 @@
 {
 optionInit(&argc, argv, options);
 
 if (argc != 2 && !optionExists("settings"))
     usage();
 
 struct trackHubCheckOptions *checkOptions = NULL;
 AllocVar(checkOptions);
 
 checkOptions->specHost = (optionExists("test") ? "genome-test.soe.ucsc.edu" : "genome.ucsc.edu");
 checkOptions->specHost = optionVal("specHost", checkOptions->specHost);
 
 checkOptions->printMeta = optionExists("printMeta");
 checkOptions->checkFiles = !optionExists("noTracks");
 checkOptions->checkSettings = optionExists("checkSettings");
+checkOptions->genome = optionVal("genome", NULL);
 
 struct trackHubSettingSpec *setting = NULL;
 AllocVar(setting);
 setting->level = optionVal("level", "all");
 if (trackHubSettingLevel(setting) < 0)
     {
     fprintf(stderr, "ERROR: Unrecognized support level %s\n\n", setting->level);
     usage();
     }
 checkOptions->level = setting->level;
 
 char *version = NULL;
 if (optionExists("version"))
     version = optionVal("version", NULL);
 checkOptions->version = version;