src/hg/encode/encodePatchTdb/encodePatchTdb.c 1.7
1.7 2010/01/05 20:15:44 kent
Fixing stanza merge problem when there is no line before stanza in patch file. Fixing replace eating a stanza. Making replace just comment out old stanza by default, but there's a noComment option. Putting in test suite.
Index: src/hg/encode/encodePatchTdb/encodePatchTdb.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/encode/encodePatchTdb/encodePatchTdb.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -b -B -U 4 -r1.6 -r1.7
--- src/hg/encode/encodePatchTdb/encodePatchTdb.c 5 Jan 2010 05:39:14 -0000 1.6
+++ src/hg/encode/encodePatchTdb/encodePatchTdb.c 5 Jan 2010 20:15:44 -0000 1.7
@@ -13,8 +13,9 @@
static char const rcsid[] = "$Id$";
char *clMode = "add";
char *clTest = NULL;
+boolean clNoComment = FALSE;
void usage()
/* Explain usage and exit. */
{
@@ -26,18 +27,21 @@
" encodePatchTdb 849/out/trackDb.ra ~/kent/src/makeDb/trackDb/human/hg18/trackDb.wgEncode.ra\n"
"options:\n"
" -mode=mode (default %s). Operate in one of the following modes\n"
" replace - replace existing records rather than doing field by field update.\n"
+ " Leaves existing record commented out.\n"
" add - add new records at end of parent's subtrack list. Complain if record isn't new\n"
" warn if it's a new track rather than just new subtracks\n"
+ " -noComment - If set will not leave old record commented out\n"
" -test=patchFile - rather than doing patches in place, write patched output to this file\n"
, clMode
);
}
static struct optionSpec options[] = {
{"mode", OPTION_STRING},
{"test", OPTION_STRING},
+ {"noComment", OPTION_BOOLEAN},
{"root", OPTION_STRING},
{NULL, 0},
};
@@ -74,8 +78,9 @@
int startLineIx, endLineIx; /* Start and end in file for error reporting. */
struct raFile *file; /* Pointer to file we are in. */
char *endComments; /* Some comments that may follow record. */
struct raRecord *subtracks; /* Subtracks of this track. */
+ boolean isRemoved; /* If set, suppresses output. */
};
struct raFile
/* A file full of ra's. */
@@ -426,32 +431,13 @@
else
break;
}
struct raRecord *recordBefore = (viewChild != NULL ? viewChild : view);
+sub->parent = view;
sub->next = recordBefore->next;
recordBefore->next = sub;
}
-void substituteIntoView(struct raRecord *sub, struct raRecord *oldSub, struct raRecord *view)
-/* Substitute sub for oldSub as a child of view. Assumes oldSub is in same file and after view. */
-{
-uglyf("substituteIntoView sub=%s oldSub=%s %p view=%s\n", sub->key, oldSub->key, oldSub, view->key);
-struct raRecord *recordBefore = NULL;
-struct raRecord *r, *prev = NULL;
-for (r = view; r != NULL; r = r->next)
- {
- if (r->next == oldSub)
- {
- recordBefore = prev;
- break;
- }
- prev = r;
- }
-assert(recordBefore != NULL);
-sub->next = oldSub->next;
-recordBefore->next = sub;
-}
-
char *firstTagInText(char *text)
/* Return the location of tag in text - skipping blank and comment lines and white-space */
{
char *s = text;
@@ -490,10 +476,40 @@
dyStringAppendC(dy, '\n');
t->text = dyStringCannibalize(&dy);
}
-void indentTdbText(struct raRecord *r, int indentCount)
-/* Add spaces to start of all text in r. */
+boolean hasBlankLine(char *text)
+/* Return TRUE if there is an empty line in text. */
+{
+char *s, *e;
+for (s = text; !isEmpty(s); s = e)
+ {
+ e = strchr(s, '\n');
+ if (e == s)
+ return TRUE;
+ else
+ e += 1;
+ }
+return FALSE;
+}
+
+void makeSureBlankLineBefore(struct raRecord *r)
+/* Make sure there is a blank line before record. */
+{
+struct raTag *first = r->tagList;
+char *firstText = first->text;
+if (!hasBlankLine(firstText))
+ {
+ int len = strlen(firstText);
+ char *newText = needMem(len+2);
+ newText[0] = '\n';
+ strcpy(newText+1, firstText);
+ first->text = newText;
+ }
+}
+
+void addToStartOfTextLines(struct raRecord *r, char c, int charCount)
+/* Add char to start of all text in r. */
{
struct raTag *t;
struct dyString *dy = dyStringNew(0);
for (t = r->tagList; t != NULL; t = t->next)
@@ -511,10 +527,10 @@
}
else
{
// Indent some extra.
- for (i=0; i<indentCount; ++i)
- dyStringAppendC(dy, ' ');
+ for (i=0; i<charCount; ++i)
+ dyStringAppendC(dy, c);
if (e == NULL)
{
dyStringAppend(dy, s);
}
@@ -529,8 +545,33 @@
}
dyStringFree(&dy);
}
+void indentTdbText(struct raRecord *r, int indentCount)
+/* Add spaces to start of all text in r. */
+{
+addToStartOfTextLines(r, ' ', indentCount);
+}
+
+void commentOutStanza(struct raRecord *r)
+/* Add # to start of all test in r. */
+{
+addToStartOfTextLines(r, '#', 1);
+}
+
+void substituteIntoView(struct raRecord *sub, struct raRecord *oldSub, struct raRecord *view)
+/* Substitute sub for oldSub as a child of view. Assumes oldSub is in same file and after view.
+ * Leaves in oldSub, but "commented out" */
+{
+sub->parent = view;
+sub->next = oldSub->next;
+oldSub->next = sub;
+if (clNoComment)
+ oldSub->isRemoved = TRUE;
+else
+ commentOutStanza(oldSub);
+}
+
void patchInSubtrack(struct raRecord *parent, struct raRecord *sub)
/* Patch sub into the correct view of parent */
{
if (hasViewSubtracks(parent))
@@ -545,8 +586,9 @@
char *release = nonNullRelease(parentRelease, subRelease);
struct raRecord *view = findRecordCompatibleWithRelease(parent->file, release, viewTrackName);
validateParentViewSub(parent, view, sub);
substituteParentText(parent, view, sub);
+ makeSureBlankLineBefore(sub);
indentTdbText(sub, 4);
struct raRecord *oldSub = findRecordCompatibleWithRelease(parent->file, release, sub->key);
if (glReplace)
{
@@ -607,9 +649,9 @@
/* Load file to patch. */
struct raFile *tdbFile = raFileRead(tdbFileName);
int oldTdbCount = slCount(tdbFile->recordList);
-if (oldTdbCount < 100)
+if (oldTdbCount < 50)
warn("%s only has %d records, I hope you meant to hit a new file\n", tdbFileName,
oldTdbCount);
linkUpParents(tdbFile);
@@ -625,14 +667,19 @@
FILE *f = mustOpen(outName, "w");
struct raRecord *r;
for (r = tdbFile->recordList; r != NULL; r = r->next)
{
+ if (!r->isRemoved)
+ {
struct raTag *tag;
for (tag = r->tagList; tag != NULL; tag = tag->next)
+ {
fputs(tag->text, f);
+ }
if (r->endComments != NULL)
fputs(r->endComments, f);
}
+ }
fputs(tdbFile->endSpace, f);
carefulClose(&f);
}
@@ -644,8 +691,9 @@
if (argc != 3)
usage();
clMode = optionVal("mode", clMode);
clTest = optionVal("test", clTest);
+clNoComment = optionExists("noComment");
if (sameString(clMode, "add"))
glReplace = FALSE;
else if (sameString(clMode, "replace"))
glReplace = TRUE;