Index: /trunk/ippTools/src/chiptool.c
===================================================================
--- /trunk/ippTools/src/chiptool.c	(revision 29415)
+++ /trunk/ippTools/src/chiptool.c	(revision 29416)
@@ -50,4 +50,5 @@
 static bool pendingcleanuprunMode(pxConfig *config);
 static bool pendingcleanupimfileMode(pxConfig *config);
+static bool revertcleanupMode(pxConfig *config);
 static bool donecleanupMode(pxConfig *config);
 static bool runMode(pxConfig *config);
@@ -94,4 +95,5 @@
         MODECASE(CHIPTOOL_MODE_PENDINGCLEANUPRUN,       pendingcleanuprunMode);
         MODECASE(CHIPTOOL_MODE_PENDINGCLEANUPIMFILE,    pendingcleanupimfileMode);
+        MODECASE(CHIPTOOL_MODE_REVERTCLEANUP,           revertcleanupMode);
         MODECASE(CHIPTOOL_MODE_DONECLEANUP,             donecleanupMode);
         MODECASE(CHIPTOOL_MODE_RUN,                     runMode);
@@ -859,9 +861,10 @@
     }
     psString query_update = pxDataGet("chiptool_revertupdatedimfile.sql");
-    if (!query) {
+    if (!query_update) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
         psFree(where);
         return false;
     }
+
 
     if (where && psListLength(where->list)) {
@@ -886,4 +889,59 @@
     }
     psFree(query_update);
+
+    return true;
+}
+static bool revertcleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-chip_id", "chipRun.chip_id", "==");
+    pxAddLabelSearchArgs (config, where, "-label", "chipRun.label", "LIKE");
+    pxAddLabelSearchArgs (config, where, "-data_group", "chipRun.data_group", "LIKE");
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+
+    char* newState = NULL;
+    if (!state) {
+        state = "error_cleaned";
+    }
+    if (!strcmp(state, "error_cleaned")) {
+        newState = "goto_cleaned";
+    } else if (!strcmp(state, "error_purged")) {
+        newState = "goto_purged";
+    } else if (!strcmp(state, "error_scrubbed")) {
+        newState = "goto_scrubbed";
+    } else {
+        psError(PXTOOLS_ERR_CONFIG, true, "-state must be either error_cleaned, error_purged, or error_scrubbed");
+        return false;
+    }
+
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = pxDataGet("chiptool_revertcleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        psFree(where);
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    psFree(where);
+
+    if (!p_psDBRunQueryF(config->dbh, query, newState, state, state)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
 
     return true;
Index: /trunk/ippTools/src/chiptool.h
===================================================================
--- /trunk/ippTools/src/chiptool.h	(revision 29415)
+++ /trunk/ippTools/src/chiptool.h	(revision 29416)
@@ -42,4 +42,5 @@
     CHIPTOOL_MODE_PENDINGCLEANUPRUN,
     CHIPTOOL_MODE_PENDINGCLEANUPIMFILE,
+    CHIPTOOL_MODE_REVERTCLEANUP,
     CHIPTOOL_MODE_DONECLEANUP,
     CHIPTOOL_MODE_RUN,
Index: /trunk/ippTools/src/chiptoolConfig.c
===================================================================
--- /trunk/ippTools/src/chiptoolConfig.c	(revision 29415)
+++ /trunk/ippTools/src/chiptoolConfig.c	(revision 29416)
@@ -290,4 +290,12 @@
     psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
 
+    // -revertcleanup
+    psMetadata *revertcleanupArgs = psMetadataAlloc();
+    psMetadataAddS64(revertcleanupArgs, PS_LIST_TAIL, "-chip_id", 0,            "search by chip ID", 0);
+    psMetadataAddStr(revertcleanupArgs,  PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by chipRun label (LIKE comparison)", NULL);
+    psMetadataAddStr(revertcleanupArgs,  PS_LIST_TAIL, "-data_group",  PS_META_DUPLICATE_OK, "search by chipRun data_group (LIKE comparison)", NULL);
+    psMetadataAddStr(revertcleanupArgs, PS_LIST_TAIL, "-state", 0,             "search by current state", NULL);
+    psMetadataAddS16(revertcleanupArgs, PS_LIST_TAIL, "-fault",  0,            "search by fault code", 0);
+
     // -run
     psMetadata *runArgs = psMetadataAlloc();
@@ -371,4 +379,5 @@
     PXOPT_ADD_MODE("-pendingcleanupimfile", "show runs that need to be cleaned up", CHIPTOOL_MODE_PENDINGCLEANUPIMFILE, pendingcleanupimfileArgs);
     PXOPT_ADD_MODE("-donecleanup",          "show runs that have been cleaned",     CHIPTOOL_MODE_DONECLEANUP,          donecleanupArgs);
+    PXOPT_ADD_MODE("-revertcleanup",        "show runs that have been cleaned",     CHIPTOOL_MODE_REVERTCLEANUP,        revertcleanupArgs);
     PXOPT_ADD_MODE("-run",                  "show runs",                            CHIPTOOL_MODE_RUN,                  runArgs);
     PXOPT_ADD_MODE("-tocleanedimfile",      "set imfile state to cleaned",          CHIPTOOL_MODE_TOCLEANEDIMFILE,      tocleanedimfileArgs);
Index: /trunk/ippTools/src/difftool.c
===================================================================
--- /trunk/ippTools/src/difftool.c	(revision 29415)
+++ /trunk/ippTools/src/difftool.c	(revision 29416)
@@ -48,4 +48,5 @@
 static bool pendingcleanuprunMode(pxConfig *config);
 static bool pendingcleanupskyfileMode(pxConfig *config);
+static bool revertcleanupMode(pxConfig *config);
 static bool donecleanupMode(pxConfig *config);
 static bool updatediffskyfileMode(pxConfig *config);
@@ -100,4 +101,5 @@
         MODECASE(DIFFTOOL_MODE_PENDINGCLEANUPRUN,     pendingcleanuprunMode);
         MODECASE(DIFFTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileMode);
+        MODECASE(DIFFTOOL_MODE_REVERTCLEANUP,         revertcleanupMode);
         MODECASE(DIFFTOOL_MODE_DONECLEANUP,           donecleanupMode);
         MODECASE(DIFFTOOL_MODE_UPDATEDIFFSKYFILE,     updatediffskyfileMode);
@@ -2531,4 +2533,61 @@
 
 
+static bool revertcleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-diff_id",    "diffSkyfile.diff_id", "==");
+    pxAddLabelSearchArgs (config, where, "-label",     "diffRun.label", "LIKE");
+    pxAddLabelSearchArgs (config, where, "-data_group",   "diffRun.data_group", "LIKE");
+
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+    }
+    if (!state) {
+        state = "error_cleaned";
+    }
+    char *newState = NULL;
+    if (!strcmp(state, "error_cleaned")) {
+        newState = "goto_cleaned";
+    } else if (!strcmp(state, "error_purged")) {
+        newState = "goto_purged";
+    } else if (!strcmp(state, "error_scrubbed")) {
+        newState = "goto_scrubbed";
+    } else {
+        psError(PXTOOLS_ERR_CONFIG, true, "-state must be either error_cleaned, error_purged, or error_scrubbed");
+        return false;
+    }
+
+    psString query = pxDataGet("difftool_revertcleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQueryF(config->dbh, query, newState, state, state)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    int numDeleted = psDBAffectedRows(config->dbh);
+
+    psLogMsg("difftool", PS_LOG_INFO, "Reverted %d diffRuns and diffSkyfiles", numDeleted);
+
+    return true;
+}
 static bool donecleanupMode(pxConfig *config)
 {
Index: /trunk/ippTools/src/difftool.h
===================================================================
--- /trunk/ippTools/src/difftool.h	(revision 29415)
+++ /trunk/ippTools/src/difftool.h	(revision 29416)
@@ -42,4 +42,5 @@
     DIFFTOOL_MODE_PENDINGCLEANUPRUN,
     DIFFTOOL_MODE_PENDINGCLEANUPSKYFILE,
+    DIFFTOOL_MODE_REVERTCLEANUP,
     DIFFTOOL_MODE_DONECLEANUP,
     DIFFTOOL_MODE_UPDATEDIFFSKYFILE,
Index: /trunk/ippTools/src/difftoolConfig.c
===================================================================
--- /trunk/ippTools/src/difftoolConfig.c	(revision 29415)
+++ /trunk/ippTools/src/difftoolConfig.c	(revision 29416)
@@ -390,4 +390,12 @@
     psMetadataAddU64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
 
+    // -revertcleanup
+    psMetadata *revertcleanupArgs = psMetadataAlloc();
+    psMetadataAddS64(revertcleanupArgs, PS_LIST_TAIL, "-diff_id", 0,            "search by difftool ID", 0);
+    psMetadataAddStr(revertcleanupArgs, PS_LIST_TAIL, "-label",  PS_META_DUPLICATE_OK, "search by diffRun label", NULL);
+    psMetadataAddStr(revertcleanupArgs, PS_LIST_TAIL, "-data_group",  PS_META_DUPLICATE_OK, "search by diffRun data_group", NULL);
+    psMetadataAddStr(revertcleanupArgs, PS_LIST_TAIL, "-state",  0,            "search by state", NULL);
+
+
     // -donecleanup
     psMetadata *donecleanupArgs = psMetadataAlloc();
@@ -464,4 +472,5 @@
     PXOPT_ADD_MODE("-pendingcleanuprun",     "show runs that need to be cleaned up", DIFFTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
     PXOPT_ADD_MODE("-pendingcleanupskyfile", "show runs that need to be cleaned up", DIFFTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileArgs);
+    PXOPT_ADD_MODE("-revertcleanup",           "revert cleanup runs with errors",     DIFFTOOL_MODE_REVERTCLEANUP,          revertcleanupArgs);
     PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     DIFFTOOL_MODE_DONECLEANUP,          donecleanupArgs);
     PXOPT_ADD_MODE("-updatediffskyfile",     "update fault code for a diffskyfile",  DIFFTOOL_MODE_UPDATEDIFFSKYFILE,          updatediffskyfileArgs);
Index: /trunk/ippTools/src/warptool.c
===================================================================
--- /trunk/ippTools/src/warptool.c	(revision 29415)
+++ /trunk/ippTools/src/warptool.c	(revision 29416)
@@ -52,4 +52,5 @@
 static bool pendingcleanuprunMode(pxConfig *config);
 static bool pendingcleanupwarpMode(pxConfig *config);
+static bool revertcleanupMode(pxConfig *config);
 static bool donecleanupMode(pxConfig *config);
 static bool tocleanedskyfileMode(pxConfig *config);
@@ -107,4 +108,5 @@
         MODECASE(WARPTOOL_MODE_PENDINGCLEANUPRUN,  pendingcleanuprunMode);
         MODECASE(WARPTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupwarpMode);
+        MODECASE(WARPTOOL_MODE_REVERTCLEANUP,      revertcleanupMode);
         MODECASE(WARPTOOL_MODE_DONECLEANUP,        donecleanupMode);
         MODECASE(WARPTOOL_MODE_TOCLEANEDSKYFILE,   tocleanedskyfileMode);
@@ -1805,4 +1807,61 @@
 
 
+static bool revertcleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id",    "warpSkyfile.warp_id", "==");
+    pxAddLabelSearchArgs (config, where, "-label",     "warpRun.label", "LIKE");
+    pxAddLabelSearchArgs (config, where, "-data_group",   "warpRun.data_group", "LIKE");
+
+    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
+
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+    }
+    if (!state) {
+        state = "error_cleaned";
+    }
+    char *newState = NULL;
+    if (!strcmp(state, "error_cleaned")) {
+        newState = "goto_cleaned";
+    } else if (!strcmp(state, "error_purged")) {
+        newState = "goto_purged";
+    } else if (!strcmp(state, "error_scrubbed")) {
+        newState = "goto_scrubbed";
+    } else {
+        psError(PXTOOLS_ERR_CONFIG, true, "-state must be either error_cleaned, error_purged, or error_scrubbed");
+        return false;
+    }
+
+    psString query = pxDataGet("warptool_revertcleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    if (!p_psDBRunQueryF(config->dbh, query, newState, state, state)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    int numDeleted = psDBAffectedRows(config->dbh);
+
+    psLogMsg("warptool", PS_LOG_INFO, "Reverted %d warpRuns and warpSkyfiles", numDeleted);
+
+    return true;
+}
 static bool donecleanupMode(pxConfig *config)
 {
Index: /trunk/ippTools/src/warptool.h
===================================================================
--- /trunk/ippTools/src/warptool.h	(revision 29415)
+++ /trunk/ippTools/src/warptool.h	(revision 29416)
@@ -48,4 +48,5 @@
     WARPTOOL_MODE_PENDINGCLEANUPRUN,
     WARPTOOL_MODE_PENDINGCLEANUPSKYFILE,
+    WARPTOOL_MODE_REVERTCLEANUP,
     WARPTOOL_MODE_DONECLEANUP,
     WARPTOOL_MODE_TOCLEANEDSKYFILE,
Index: /trunk/ippTools/src/warptoolConfig.c
===================================================================
--- /trunk/ippTools/src/warptoolConfig.c	(revision 29415)
+++ /trunk/ippTools/src/warptoolConfig.c	(revision 29416)
@@ -362,4 +362,11 @@
     psMetadataAddU64(pendingcleanupskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
 
+    // -revertcleanup
+    psMetadata *revertcleanupArgs = psMetadataAlloc();
+    psMetadataAddS64(revertcleanupArgs, PS_LIST_TAIL, "-warp_id", 0,            "search by warptool ID", 0);
+    psMetadataAddStr(revertcleanupArgs, PS_LIST_TAIL, "-label",  PS_META_DUPLICATE_OK, "search by warpRun label", NULL);
+    psMetadataAddStr(revertcleanupArgs, PS_LIST_TAIL, "-data_group",  PS_META_DUPLICATE_OK, "search by warpRun data_group", NULL);
+    psMetadataAddStr(revertcleanupArgs, PS_LIST_TAIL, "-state",  0,            "search by state", NULL);
+
     // -donecleanup
     psMetadata *donecleanupArgs = psMetadataAlloc();
@@ -451,4 +458,5 @@
     PXOPT_ADD_MODE("-pendingcleanuprun",     "show runs that need to be cleaned up", WARPTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
     PXOPT_ADD_MODE("-pendingcleanupskyfile", "show runs that need to be cleaned up", WARPTOOL_MODE_PENDINGCLEANUPSKYFILE, pendingcleanupskyfileArgs);
+    PXOPT_ADD_MODE("-revertcleanup",         "revert cleanup runs with errors",     WARPTOOL_MODE_REVERTCLEANUP,          revertcleanupArgs);
     PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     WARPTOOL_MODE_DONECLEANUP,          donecleanupArgs);
     PXOPT_ADD_MODE("-tocleanedskyfile", "set skyfile as cleaned", WARPTOOL_MODE_TOCLEANEDSKYFILE, tocleanedskyfileArgs);
