fde90be0141f2a9f4ecbe31f394f05b10d2f03f3
chmalee
  Tue May 14 09:12:20 2019 -0700
Moving the parents and children hub check into the hubCheck program, refs #13428

diff --git src/hg/utils/hubCheck/hubCheck.c src/hg/utils/hubCheck/hubCheck.c
index d870182..7696ad2 100644
--- src/hg/utils/hubCheck/hubCheck.c
+++ src/hg/utils/hubCheck/hubCheck.c
@@ -443,30 +443,55 @@
     {
     /*  check level */
     struct trackHubSettingSpec *checkLevel = NULL;
     AllocVar(checkLevel);
     checkLevel->level = options->level;
     if (trackHubSettingLevel(hubSetting) < trackHubSettingLevel(checkLevel))
         {
         dyStringPrintf(errors, "Setting '%s' is level '%s'\n", setting, hubSetting->level);
         retVal = 1;
         }
     freez(&checkLevel);
     }
 return retVal;
 }
 
+void hubCheckParentsAndChildren(struct trackDb *tdb)
+/* Check that a single trackDb stanza has the correct parent and subtrack pointers */
+{
+if (tdbIsSuper(tdb) || tdbIsComposite(tdb) || tdbIsCompositeView(tdb) || tdbIsContainer(tdb))
+    {
+    if (tdb->subtracks == NULL)
+        {
+        errAbort("Track \"%s\" is declared superTrack, compositeTrack, view or "
+            "container, but has no subtracks", tdb->track);
+        }
+
+    // Containers should not have a bigDataUrl setting
+    if (trackDbLocalSetting(tdb, "bigDataUrl"))
+        {
+        errAbort("Track \"%s\" is declared superTrack, compositeTrack, view or "
+            "container, and also has a bigDataUrl", tdb->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);
+    }
+}
+
 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;
 
 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)
         retVal |= hubCheckTrackSetting(hub, tdb, hel->name, options, errors);
@@ -484,30 +509,31 @@
         for(pair = metaPairs; pair; pair = pair->next)
             {
             printf("\t%s : %s\n", pair->name, (char *)pair->val);
             }
         printf("\n");
         }
     slPairFreeValsAndList(&metaPairs);
     }
 
 if (!options->checkFiles)
     return retVal;
 
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
+    hubCheckParentsAndChildren(tdb);
     hubCheckBigDataUrl(hub, genome, tdb);
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     {
     retVal = 1;
     dyStringPrintf(errors, "%s", errCatch->message->string);
     }
 errCatchFree(&errCatch);
 
 return retVal;
 }
 
 
 int hubCheckGenome(struct trackHub *hub, struct trackHubGenome *genome,