2c1edfc333aea4ff30046df5a89f9a150ecf5c78
kent
  Thu Oct 28 14:51:11 2010 -0700
Adding trackHubAddNamePrefix to help give hubs their own name space within cart.
diff --git src/hg/lib/trackHub.c src/hg/lib/trackHub.c
index ddd01de..17f2dd0 100644
--- src/hg/lib/trackHub.c
+++ src/hg/lib/trackHub.c
@@ -177,30 +177,43 @@
 *pList = NULL;
 }
 
 static char *requiredSetting(struct trackHub *hub, struct trackHubGenome *genome,
 	struct trackDb *tdb, char *setting)
 /* Fetch setting or give an error message, a little more specific than the
  * error message from trackDbRequiredSetting(). */
 {
 char *val = trackDbSetting(tdb, setting);
 if (val == NULL)
     errAbort("Missing required %s setting in hub %s genome %s track %s", setting,
     	hub->url, genome->name, tdb->track);
 return val;
 }
 
+static void expandBigDataUrl(struct trackHub *hub, struct trackHubGenome *genome,
+	struct trackDb *tdb)
+/* Expand bigDataUrls so that no longer relative to genome->trackDbFile */
+{
+struct hashEl *hel = hashLookup(tdb->settingsHash, "bigDataUrl");
+if (hel != NULL)
+    {
+    char *oldVal = hel->val;
+    hel->val = trackHubRelativeUrl(genome->trackDbFile, oldVal);
+    freeMem(oldVal);
+    }
+}
+
 static void checkTagsLegal(struct trackHub *hub, struct trackHubGenome *genome,
 	struct trackDb *tdb)
 /* Make sure that tdb has all the required tags and is of a supported type. */
 {
 /* Check for existence of fields required in all tracks */
 requiredSetting(hub, genome, tdb, "shortLabel");
 requiredSetting(hub, genome, tdb, "longLabel");
 
 /* Further checks depend whether it is a container. */
 if (tdb->subtracks != NULL)
     {
     if (trackDbSetting(tdb, "compositeTrack"))
         {
 	}
     else if (trackDbSetting(tdb, "container"))
@@ -234,48 +247,90 @@
 struct trackHubGenome *trackHubFindGenome(struct trackHub *hub, char *genomeName)
 /* Return trackHubGenome of given name associated with hub.  Return NULL if no
  * such genome. */
 {
 return hashFindVal(hub->genomeHash, genomeName);
 }
 
 struct trackDb *trackHubTracksForGenome(struct trackHub *hub, struct trackHubGenome *genome)
 /* Get list of tracks associated with genome.  Check that it only is composed of legal
  * types.  Do a few other quick checks to catch errors early. */
 {
 struct lineFile *lf = udcWrapShortLineFile(genome->trackDbFile, NULL, 16*1024*1024);
 struct trackDb *tdbList = trackDbFromOpenRa(lf);
 lineFileClose(&lf);
 
+/* Make bigDataUrls more absolute rather than relative to genome.ra dir */
+struct trackDb *tdb;
+for (tdb = tdbList; tdb != NULL; tdb = tdb->next)
+    expandBigDataUrl(hub, genome, tdb);
+
 /* Connect up subtracks and parents.  Note this loop does not actually move tracks
  * from list to parent subtracks, it just uses the field as a marker. Just do this
  * so when doing error checking can distinguish between container tracks and others.
  * This does have the pleasant side effect of making good error messages for
  * non-existant parents. */
-struct trackDb *tdb;
 struct hash *hash = hashNew(0);
 for (tdb = tdbList; tdb != NULL; tdb = tdb->next)
     hashAdd(hash, tdb->track, tdb);
 for (tdb = tdbList; tdb != NULL; tdb = tdb->next)
     {
     char *parentName = trackDbLocalSetting(tdb, "parent");
     if (parentName != NULL)
          {
 	 struct trackDb *parent = hashFindVal(hash, parentName);
 	 if (parent == NULL)
 	    errAbort("Parent %s of track %s doesn't exist in hub %s genome %s", parentName,
 		tdb->track, hub->url, genome->name);
 	 tdb->parent = parent;
 	 parent->subtracks = tdb;
 	 }
     }
 hashFree(&hash);
 
 /* Loop through list checking tags and removing ad-hoc use of parent and subtracks tags. */
 for (tdb = tdbList; tdb != NULL; tdb = tdb->next)
     {
     checkTagsLegal(hub, genome, tdb);
     tdb->parent = tdb->subtracks = NULL;
     }
 return tdbList;
 }
 
+static void reprefixString(char **pString, char *prefix)
+/* Replace *pString with prefix + *pString, freeing
+ * whatever was in *pString before. */
+{
+char *oldName = *pString;
+*pString = catTwoStrings(prefix, oldName);
+freeMem(oldName);
+}
+
+static void addPrefixToSetting(struct hash *settings, char *key, char *prefix)
+/* Given a settings hash, which is string valued.  Old values will be freed. */
+{
+struct hashEl *hel = hashLookup(settings, key);
+if (hel != NULL)
+    reprefixString((char **)&hel->val, prefix);
+}
+
+static void trackDbListAddNamePrefix(struct trackDb *tdbList, char *prefix)
+/* Surgically alter tdbList so that it works as if every track was
+ * renamed so as to add a prefix to it's name. */
+{
+struct trackDb *tdb;
+for (tdb = tdbList; tdb != NULL; tdb = tdb->next)
+    {
+    addPrefixToSetting(tdb->settingsHash, "track", prefix);
+    addPrefixToSetting(tdb->settingsHash, "parent", prefix);
+    reprefixString(&tdb->track, prefix);
+    }
+}
+
+void trackHubAddNamePrefix(char *hubName, struct trackDb *tdbList)
+/* For a hub named "xyz" add the prefix "hub_xyz_" to each track and parent field. */
+{
+char namePrefix[PATH_LEN];
+safef(namePrefix, sizeof(namePrefix), "hub_%s_", hubName);
+trackDbListAddNamePrefix(tdbList, namePrefix);
+}
+