src/hg/utils/tdbQuery/tdbQuery.c 1.22

1.22 2009/12/07 17:19:13 kent
Rewriting to get rid of visibility.ra and priority.ra files.
Index: src/hg/utils/tdbQuery/tdbQuery.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/utils/tdbQuery/tdbQuery.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -b -B -U 4 -r1.21 -r1.22
--- src/hg/utils/tdbQuery/tdbQuery.c	7 Dec 2009 02:37:39 -0000	1.21
+++ src/hg/utils/tdbQuery/tdbQuery.c	7 Dec 2009 17:19:13 -0000	1.22
@@ -8,8 +8,9 @@
 #include "obscure.h"
 #include "portable.h"
 #include "errabort.h"
 #include "tdbRecord.h"
+#include "ra.h"
 #include "hdb.h"  /* Just for strict option. */
 #include "rql.h"
 
 static char const rcsid[] = "$Id$";
@@ -1061,12 +1062,175 @@
 
 rqlStatementFree(&rql);
 }
 
+struct slName *hashPair(char *raFile, char *keyField, char *valField, struct hash **retValHash,
+	struct hash **retCommentHash)
+/* Read two fields out of a ra file.  For records that have both fields put them into
+ * a hash with the logical keys and values, which is returned.  Return list of keys in order. */
+{
+struct slName *list = NULL, *el;
+struct hash *hash = hashNew(0), *commentHash = hashNew(0);
+struct lineFile *lf = lineFileMayOpen(raFile, TRUE);
+struct dyString *dy = dyStringNew(0);
+if (lf != NULL)
+    {
+    while (raSkipLeadingEmptyLines(lf, dy))
+	{
+	char *theKey = NULL, *theVal = NULL;
+	char *name, *val;
+	while (raNextTagVal(lf, &name, &val, NULL))
+	    {
+	    if (sameString(name, keyField))
+	       theKey = lmCloneString(hash->lm, val);
+	    else if (sameString(name, valField))
+	       theVal = lmCloneString(hash->lm, val);
+	    }
+	if (theKey && theVal)
+	    {
+	    hashAdd(hash, theKey, theVal);
+	    hashAdd(commentHash, theKey, lmCloneString(hash->lm, dy->string));
+	    slNameAddHead(&list, theKey);
+	    }
+	}
+    lineFileClose(&lf);
+    }
+dyStringFree(&dy);
+*retValHash = hash;
+*retCommentHash = commentHash;
+slReverse(&list);
+return list;
+}
+
+void overrideOrWriteSelf(char *orig, char *name, char *val, 
+	char *tagName, char *keyVal, struct hash *hash, struct lineFile *lf, FILE *f)
+/* Write out name/val pair. */
+{
+if (keyVal == NULL)
+    errAbort("%s tag before track tag line %d of %s", tagName, lf->lineIx, lf->fileName);
+char *newVal = hashFindVal(hash, keyVal);
+if (newVal != NULL)
+    {
+    int leadingSpaces = skipLeadingSpaces(orig) - orig;
+    if (orig[0] == '#')
+        errAbort("Rats, internal comments, can't deal with it.");
+    mustWrite(f, orig, leadingSpaces);
+    fprintf(f, "%s %s\n", name, newVal);
+    hashRemove(hash, keyVal);
+    }
+else
+    fprintf(f, "%s", orig);
+}
+
 void rewriteWithVisAndPriUpdates(char *tIn, char *pIn, char *vIn, char *tOut)
 /* Write tIn to tOut applying modifications in pIn and pOut */
 {
-uglyf("rewriting %s to %s\n", tIn, tOut);
+struct hash *pHash, *pTextHash;
+struct slName *pList = hashPair(pIn, "track", "priority", &pHash, &pTextHash);
+struct hash *vHash, *vTextHash;
+struct slName *vList = hashPair(vIn, "track", "visibility", &vHash, &vTextHash);
+struct lineFile *lf = lineFileOpen(tIn, TRUE);
+FILE *f = mustOpen(tOut, "w");
+struct dyString *dy = dyStringNew(0);
+while (raSkipLeadingEmptyLines(lf, dy))
+    {
+    fprintf(f, "%s", dy->string);
+    dyStringClear(dy);
+    char *keyVal = NULL;
+    char *name, *val;
+    while (raNextTagVal(lf, &name, &val, dy))
+        {
+	if (sameString(glKeyField, name))
+	    {
+	    fprintf(f, "%s", dy->string);
+	    keyVal = cloneString(val);
+	    }
+	else if (sameString("priority", name))
+	    {
+	    overrideOrWriteSelf(dy->string, name, val, "priority", keyVal, pHash, lf, f);
+	    }
+	else if (sameString("visibility", name))
+	    {
+	    overrideOrWriteSelf(dy->string, name, val, "visibility", keyVal, vHash, lf, f);
+	    }
+	else
+	    {
+	    fprintf(f, "%s", dy->string);
+	    }
+	dyStringClear(dy);
+	}
+    fprintf(f, "%s", dy->string);
+    }
+struct slName *p, *v;
+boolean pWroteHead = FALSE;
+for (p = pList; p != NULL; p = p->next)
+    {
+    char *key = p->name;
+    char *pri = hashFindVal(pHash, key);
+    if (pri != NULL)
+        {
+	if (!pWroteHead)
+	    {
+	    fprintf(f, "\n#Overrides from priority.ra\n\n");
+	    pWroteHead = TRUE;
+	    }
+	char *text = hashFindVal(pTextHash, key);
+	fprintf(f, "%s", text);
+	char *vis = hashFindVal(vHash, key);
+	if (vis != NULL)
+	    {
+	    char *vText = hashFindVal(vTextHash, key);
+	    fprintf(f, "%s", vText);
+	    }
+	fprintf(f, "track %s override\n", key);
+	fprintf(f, "priority %s\n", pri);
+	if (vis != NULL)
+	    fprintf(f, "visibility %s\n", vis);
+	fprintf(f, "\n");
+	}
+    }
+boolean vWroteHead = FALSE;
+for (v = vList; v != NULL; v = v->next)
+    {
+    char *key = v->name;
+    char *vis = hashFindVal(vHash, key);
+    if (vis != NULL)
+        {
+	char *text = hashFindVal(vTextHash, key);
+	if (!vWroteHead)
+	    {
+	    fprintf(f, "\n#Overrides from visibility.ra\n\n");
+	    vWroteHead = TRUE;
+	    }
+	fprintf(f, "%s", text);
+	fprintf(f, "track %s override\n", key);
+	fprintf(f, "visibility %s\n", vis);
+	fprintf(f, "\n");
+	}
+    }
+dyStringFree(&dy);
+carefulClose(&f);
+lineFileClose(&lf);
+}
+
+static void rewriteInsideSubdir(char *outDir, char *inDir, char *subDir,
+	char *trackFile, char *visFile, char *priFile)
+/* Do some sort of rewrite on one subdirectory. */
+{
+char tIn[PATH_LEN], vIn[PATH_LEN], pIn[PATH_LEN];
+safef(tIn, sizeof(tIn), "%s/%s", inDir, trackFile);
+safef(vIn, sizeof(vIn), "%s/%s", inDir, visFile);
+safef(pIn, sizeof(pIn), "%s/%s", inDir, priFile);
+if (fileExists(tIn))
+     {
+     if (fileExists(pIn) || fileExists(vIn))
+	 {
+	 char tOut[PATH_LEN];
+	 safef(tOut, sizeof(tOut), "%s/%s", outDir, trackFile);
+	 makeDirsOnPath(outDir);
+	 rewriteWithVisAndPriUpdates(tIn, pIn, vIn, tOut);
+	 }
+     }
 }
 
 void doRewrite(char *outDir, char *inDir, char *trackFile, char *visFile, char *priFile)
 /* Do some sort of rewrite on entire system. */
@@ -1078,19 +1242,18 @@
 	{
 	char inOrgDir[PATH_LEN], outOrgDir[PATH_LEN];
 	safef(inOrgDir, sizeof(inOrgDir), "%s/%s", inDir, org->name);
 	safef(outOrgDir, sizeof(outOrgDir), "%s/%s", outDir, org->name);
-	char tInOrg[PATH_LEN], vInOrg[PATH_LEN], pInOrg[PATH_LEN];
-	safef(tInOrg, sizeof(tInOrg), "%s/%s", inOrgDir, trackFile);
-	safef(vInOrg, sizeof(vInOrg), "%s/%s", inOrgDir, visFile);
-	safef(pInOrg, sizeof(pInOrg), "%s/%s", inOrgDir, priFile);
-	if (fileExists(tInOrg))
-	     {
-	     if (fileExists(pInOrg) || fileExists(vInOrg))
-		 {
-		 char tOutOrg[PATH_LEN];
-		 safef(tOutOrg, sizeof(tOutOrg), "%s/%s", outOrgDir, trackFile);
-		 rewriteWithVisAndPriUpdates(tInOrg, pInOrg, vInOrg, tOutOrg);
+	rewriteInsideSubdir(outOrgDir, inOrgDir, org->name, trackFile, visFile, priFile);
+	struct fileInfo *db, *dbList = listDirX(inOrgDir, "*", FALSE);
+	for (db = dbList; db != NULL; db = db->next)
+	    {
+	    if (db->isDir)
+	        {
+		char inDbDir[PATH_LEN], outDbDir[PATH_LEN];
+		safef(inDbDir, sizeof(inDbDir), "%s/%s", inOrgDir, db->name);
+		safef(outDbDir, sizeof(outDbDir), "%s/%s", outOrgDir, db->name);
+		rewriteInsideSubdir(outDbDir, inDbDir, db->name, trackFile, visFile, priFile);
 		 }
 	     }
 	}
     }