src/hg/makeDb/trackDbPatch/trackDbPatch.c 1.1
1.1 2009/11/22 23:56:30 kent
Starting to work on utility to patch trackDb files. Just reads one of two inputs at the moment, no output.
Index: src/hg/makeDb/trackDbPatch/trackDbPatch.c
===================================================================
RCS file: src/hg/makeDb/trackDbPatch/trackDbPatch.c
diff -N src/hg/makeDb/trackDbPatch/trackDbPatch.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/hg/makeDb/trackDbPatch/trackDbPatch.c 22 Nov 2009 23:56:30 -0000 1.1
@@ -0,0 +1,126 @@
+/* trackDbPatch - Patch files in trackDb with a specification .ra file that has db, track, and file fields that say where to apply the patch, and other fields that are patched in.. */
+#include "common.h"
+#include "linefile.h"
+#include "hash.h"
+#include "options.h"
+#include "ra.h"
+
+static char const rcsid[] = "$Id$";
+
+char *clPatchDir = NULL;
+char *clKey = "track";
+
+void usage()
+/* Explain usage and exit. */
+{
+errAbort(
+ "trackDbPatch - Patch files in trackDb with a specification .ra file that has db, track, and file fields that say where to apply the patch, and other fields that are patched in.\n"
+ "usage:\n"
+ " trackDbPatch patches.ra backupDir\n"
+ "options:\n"
+ " -test=patchDir - rather than doing patches in place, write patched output to this dir\n"
+ " -key=tagName - use tagName as key. Default '%s'\n"
+ , clKey
+ );
+}
+
+static struct optionSpec options[] = {
+ {NULL, 0},
+};
+
+struct raPatch
+/* A patch record. */
+ {
+ struct raPatch *next;
+ char *db; /* Database. */
+ char *track; /* Track. */
+ struct slName *fileList; /* List of files. */
+ struct slPair *tagList; /* List of tags to merge in. */
+ };
+
+static struct slName *makeFileList(char *filesAndPos)
+/* Convert something that looks like "file # file #" to a list of files. This
+ * writes zeroes into the filesAndPos input. */
+{
+struct slName *list = NULL;
+char *word;
+while ((word = nextWord(&filesAndPos)) != NULL)
+ {
+ slNameAddTail(&list, word);
+ word = nextWord(&filesAndPos);
+ if (word == NULL && !isdigit(word[0]))
+ errAbort("Expecting number in makeFileList, got %s", word);
+ }
+return list;
+}
+
+struct raPatch *raPatchReadOne(struct lineFile *lf)
+/* Read next patch from lineFile. */
+{
+struct slPair *tagList = raNextRecordAsSlPairList(lf);
+if (tagList == NULL)
+ return NULL;
+
+/* Go through tag list, diverting some tags to be actual fields in patch. */
+struct slPair *newTagList = NULL, *tag, *next;
+struct raPatch *patch;
+AllocVar(patch);
+for (tag = tagList; tag != NULL; tag = next)
+ {
+ next = tag->next;
+ if (sameString(tag->name, "db"))
+ {
+ patch->db = tag->val;
+ freez(&tag);
+ }
+ else if (sameString(tag->name, clKey))
+ {
+ patch->track = tag->val;
+ freez(&tag);
+ }
+ else if (sameString(tag->name, "file"))
+ {
+ patch->fileList = makeFileList(tag->val);
+ freeMem(tag->val);
+ freez(&tag);
+ }
+ else
+ {
+ slAddHead(&newTagList, tag);
+ }
+ }
+slReverse(&newTagList);
+
+if (patch->track == NULL)
+ errAbort("Missing %s tag before line %d of %s", clKey, lf->lineIx, lf->fileName);
+if (patch->fileList == NULL)
+ errAbort("Missing %s tag before line %d of %s", "file", lf->lineIx, lf->fileName);
+return patch;
+}
+
+void trackDbPatch(char *patchesFile, char *backupDir)
+/* trackDbPatch - Patch files in trackDb with a specification .ra file that has db, track, and file fields that say
+ * where to apply the patch, and other fields that are patched in.. */
+{
+/* Read in patch file. */
+struct lineFile *lf = lineFileOpen(patchesFile, TRUE);
+struct raPatch *patch, *patchList = NULL;
+while ((patch = raPatchReadOne(lf)) != NULL)
+ slAddHead(&patchList, patch);
+slReverse(&patchList);
+verbose(1, "Got %d patches in %s\n", slCount(patchList), patchesFile);
+
+lineFileClose(&lf);
+}
+
+int main(int argc, char *argv[])
+/* Process command line. */
+{
+optionInit(&argc, argv, options);
+if (argc != 3)
+ usage();
+clKey = optionVal("key", clKey);
+clPatchDir = optionVal("test", clPatchDir);
+trackDbPatch(argv[1], argv[2]);
+return 0;
+}