9a75927131a1e282aadced123687234bd9340c6d
braney
  Thu Feb 8 12:00:38 2018 -0800
sort metadata by name if it comes from "metadata" statements in a
trackDb

diff --git src/hg/lib/trackDbCustom.c src/hg/lib/trackDbCustom.c
index c646875..d2f9e34 100644
--- src/hg/lib/trackDbCustom.c
+++ src/hg/lib/trackDbCustom.c
@@ -1411,30 +1411,38 @@
 int ii;
 struct slPair *pairList = NULL;
 for(ii=0; ii < cachedTable->fieldCount; ii++)
     {
     char *fieldName = cachedTable->fields[ii];
     char *fieldVal = fr->row[ii];
     if (!isEmpty(fieldVal))
         slAddHead(&pairList, slPairNew(fieldName, cloneString(fieldVal)));
     }
 slReverse(&pairList);
 
 return pairList;
 }
 
 
+int cmpPairAlpha(const void *e1, const void *e2)
+/* used with slSort to sort slPairs alphabetically */
+{
+const struct slPair *a = *((struct slPair **)e1);
+const struct slPair *b = *((struct slPair **)e2);
+return strcmp(a->name, b->name);
+}
+
 static struct slPair *convertNameValueString(char *string)
 /* Convert a string composed of name=value pairs separated by white space. */
 {
 char *clone = cloneString(string);
 int count = chopByWhiteRespectDoubleQuotes(clone,NULL,0);
 char **words = needMem(sizeof(char *) * count);
 count = chopByWhiteRespectDoubleQuotes(clone,words,count);
 if (count < 1 || words[0] == NULL)
     {
     errAbort("This is not formatted var=val pairs:\n\t%s\n",string);
     }
 
 int ix;
 struct slPair *pairList = NULL, *pair;
 
@@ -1444,31 +1452,31 @@
         break;
     
     if (strchr(words[ix], '=') == NULL) // treat this the same as "var="
         {
         pair = slPairNew(words[ix], NULL);
         }   
     else
         {   
         char *name = cloneNextWordByDelimiter(&(words[ix]),'=');
         char *value = cloneString(words[ix]);
         pair = slPairNew(name, value);
         }
     slAddHead(&pairList, pair);
     }
 
-slReverse(&pairList);
+slSort(&pairList, cmpPairAlpha);
 
 return pairList;
 }
 
 struct slPair *trackDbMetaPairs(struct trackDb *tdb)
 /* Read in metadata given a trackDb entry.  This routine understands the three ways
  * that metadata can be represented in a trackDb stanza: "metadata" lines per stanza,
  * or a  tab-separated or tagStorm file with a foreign key specified by the "meta" tag.
  */
 {
 char *metaTag = trackDbSetting(tdb, "meta");
 if (metaTag != NULL)
     {
     char *tabSepMeta = trackDbSetting(tdb, "metaTab");
     if (tabSepMeta)