Index: branches/pap/ippTools/src/difftool.c
===================================================================
--- branches/pap/ippTools/src/difftool.c	(revision 27708)
+++ branches/pap/ippTools/src/difftool.c	(revision 28003)
@@ -57,4 +57,6 @@
 static bool toscrubbedskyfileMode(pxConfig *config);
 static bool tofullskyfileMode(pxConfig *config);
+static bool listrunMode(pxConfig *config);
+static bool setskyfiletoupdateMode(pxConfig *config);
 
 
@@ -101,4 +103,6 @@
         MODECASE(DIFFTOOL_MODE_TOSCRUBBEDSKYFILE,     toscrubbedskyfileMode);
         MODECASE(DIFFTOOL_MODE_TOFULLSKYFILE,         tofullskyfileMode);
+        MODECASE(DIFFTOOL_MODE_LISTRUN,               listrunMode);
+        MODECASE(DIFFTOOL_MODE_SETSKYFILETOUPDATE,    setskyfiletoupdateMode);
 
         default:
@@ -194,4 +198,5 @@
     PXOPT_COPY_S64(config->args, where, "-diff_id",  "diff_id",   "==");
     PXOPT_COPY_STR(config->args, where, "-label",     "label",     "==");
+    PXOPT_COPY_STR(config->args, where, "-data_group","data_group",     "==");
     PXOPT_COPY_STR(config->args, where, "-state",     "state",     "==");
     if (!psListLength(where->list)) {
@@ -702,4 +707,5 @@
     pxAddLabelSearchArgs (config, where, "-data_group", "diffRun.data_group", "LIKE");
 
+    PXOPT_LOOKUP_BOOL(pstamp_order, config->args, "-pstamp_order", false);
     PXOPT_LOOKUP_BOOL(template, config->args, "-template", false);
     if (!template) {
@@ -745,4 +751,12 @@
     psFree(where);
 
+    if (pstamp_order) {
+        if (template) {
+            psStringAppend(&query, " ORDER BY rawTemplate.exp_id, diff_id DESC");
+        } else {
+            psStringAppend(&query, " ORDER BY rawInput.exp_id, diff_id DESC");
+        }
+    }
+            
     // treat limit == 0 as "no limit"
     if (limit) {
@@ -810,48 +824,13 @@
     }
 
-    if (!psDBTransaction(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(where);
-        return false;
-    }
-
-    // Update state to 'new'
-    {
-        psString query = pxDataGet("difftool_revertdiffskyfile_update.sql");
-        if (!query) {
-            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            return false;
-        }
-
-        if (psListLength(where->list)) {
-            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-            psStringAppend(&query, " AND %s", whereClause);
-            psFree(whereClause);
-        }
-
-        if (!p_psDBRunQuery(config->dbh, query)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(query);
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            return false;
-        }
-        psFree(query);
-
-        psLogMsg("difftool", PS_LOG_INFO, "Updated %" PRIu64 " rows", psDBAffectedRows(config->dbh));
-    }
-
-    // Delete product
     {
         psString query = pxDataGet("difftool_revertdiffskyfile_delete.sql");
         if (!query) {
             psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
+            return false;
+        }
+        psString query_updated = pxDataGet("difftool_revertdiffskyfile_updated.sql");
+        if (!query_updated) {
+            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
             return false;
         }
@@ -860,4 +839,5 @@
             psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
             psStringAppend(&query, " AND %s", whereClause);
+            psStringAppend(&query_updated, " AND %s", whereClause);
             psFree(whereClause);
         }
@@ -866,20 +846,21 @@
             psError(PS_ERR_UNKNOWN, false, "database error");
             psFree(query);
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
             return false;
         }
         psFree(query);
-
         psLogMsg("difftool", PS_LOG_INFO, "Deleted %" PRIu64 " rows", psDBAffectedRows(config->dbh));
+
+        if (!p_psDBRunQuery(config->dbh, query_updated)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query_updated);
+            return false;
+        }
+        psFree(query_updated);
+
+        psLogMsg("difftool", PS_LOG_INFO, "Updated %" PRIu64 " rows", psDBAffectedRows(config->dbh));
     }
 
     psFree(where);
 
-    if (!psDBCommit(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
 
     return true;
@@ -971,16 +952,16 @@
         return false;
     }
-    psS16 diff_mode = 0;
+    psS16 diff_mode = IPP_DIFF_MODE_UNDEFINED;
     if ((input_warp_id != PS_MAX_S64) && (template_warp_id != PS_MAX_S64)) {
-      diff_mode = 1;
+      diff_mode = IPP_DIFF_MODE_WARP_WARP;
     }
     else if ((input_warp_id != PS_MAX_S64) && (template_stack_id != PS_MAX_S64)) {
-      diff_mode = 2;
+      diff_mode = IPP_DIFF_MODE_WARP_STACK;
     }
     else if ((input_stack_id != PS_MAX_S64) && (template_warp_id != PS_MAX_S64)) {
-      diff_mode = 3;
+      diff_mode = IPP_DIFF_MODE_STACK_WARP;
     }
     else if ((input_stack_id != PS_MAX_S64) && (template_stack_id != PS_MAX_S64)) {
-      diff_mode = 4;
+      diff_mode = IPP_DIFF_MODE_STACK_STACK;
     }
 
@@ -1366,5 +1347,4 @@
         }
 
-
         psString filter = psMetadataLookupStr(&mdok, row, "filter");
         if (!mdok) {
@@ -1378,4 +1358,20 @@
             return false;
         }
+
+	psString warp_data_group = psMetadataLookupStr(&mdok, row, "data_group");
+	if (!mdok) {
+	  psError(PXTOOLS_ERR_PROG, false, "warp data_group not found");
+	  psFree(warp2Query);
+	  psFree(stackQuery);
+	  psFree(skycell_query);
+	  if (!psDBRollback(config->dbh)) {
+	    psError(PS_ERR_UNKNOWN, false, "database error");
+	  }
+	  return false;
+	}
+	if (warp_data_group) {
+	  data_group = warp_data_group;
+	}
+	
         if (!p_psDBRunQueryF(config->dbh, skycell_query, stackQuery, warp_id, filter, warp2Query)) {
             psError(PS_ERR_UNKNOWN, false, "database error");
@@ -1416,5 +1412,5 @@
                 true,                   // exposure
                 0,       // magicked
-                2,       // diff_mode for warp-stack difference
+                IPP_DIFF_MODE_WARP_STACK,
                 note
         );
@@ -1739,4 +1735,9 @@
         const char *template = psMetadataLookupStr(NULL, row, "template_warp_id");
         const char *tess_id = psMetadataLookupStr(NULL, row, "tess_id");
+	psString input_data_group = psMetadataLookupStr(NULL, row, "input_data_group");
+	if (input_data_group) {
+	  data_group = input_data_group;
+	}
+
         if (!input_id || !template || !tess_id) {
             psError(PXTOOLS_ERR_PROG, false, "Identifiers not found");
@@ -1749,5 +1750,5 @@
             return false;
         }
-
+	
         diffRunRow *run = diffRunRowAlloc(0,
                                           "reg",
@@ -1763,5 +1764,5 @@
                                           true,  // exposure
                                           false, // magicked
-                                          1,     // diff_mode for warp-warp diff
+                                          IPP_DIFF_MODE_WARP_WARP,
                                           note); // Run to insert
         if (!diffRunInsertObject(config->dbh, run)) {
@@ -2045,5 +2046,5 @@
                                       false,                 // exposure
                                       0,       // magicked
-                                      4,       // diff_mode
+                                      IPP_DIFF_MODE_STACK_STACK, // diff_mode
                                       note
                                       );
@@ -2338,4 +2339,5 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-diff_id",   "diff_id",   "==");
+    PXOPT_COPY_STR(config->args, where, "-skycell_id", "skycell_id",   "==");
 
     if (!pxSetFaultCode(config->dbh, "diffSkyfile", where, fault)) {
@@ -2606,2 +2608,148 @@
   return true;
 }
+
+static bool listrunMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-diff_id", "diffRun.diff_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-tess_id", "diffRun.tess_id", "==");
+    PXOPT_COPY_S64(config->args, where,  "-magicked", "diffRun.magicked", "==");
+    pxAddLabelSearchArgs (config, where, "-label", "diffRun.label", "LIKE");
+    pxAddLabelSearchArgs (config, where, "-data_group", "diffRun.data_group", "LIKE");
+    pxAddLabelSearchArgs (config, where, "-dist_group", "diffRun.dist_group", "LIKE");
+
+    PXOPT_LOOKUP_BOOL(template, config->args, "-template", false);
+    if (!template) {
+        PXOPT_COPY_S64(config->args, where, "-exp_id", "rawInput.exp_id", "==");
+        PXOPT_COPY_STR(config->args, where, "-exp_name", "rawInput.exp_name", "==");
+        PXOPT_COPY_STR(config->args, where, "-warp_id", "warpInput.warp_id", "==");
+        PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "rawInput.dateobs",  ">=");
+        PXOPT_COPY_TIME(config->args, where, "-dateobs_end",   "rawInput.dateobs",  "<=");
+        PXOPT_COPY_STR(config->args, where, "-filter",     "rawInput.filter", "LIKE");
+    } else {
+        PXOPT_COPY_S64(config->args, where, "-exp_id", "rawTemplate.exp_id", "==");
+        PXOPT_COPY_STR(config->args, where, "-exp_name", "rawTemplate.exp_name", "==");
+        PXOPT_COPY_STR(config->args, where, "-warp_id", "warpTemplate.warp_id", "==");
+        PXOPT_COPY_TIME(config->args, where, "-dateobs_begin", "rawTemplate.dateobs",  ">=");
+        PXOPT_COPY_TIME(config->args, where, "-dateobs_end",   "rawTemplate.dateobs",  "<=");
+        PXOPT_COPY_STR(config->args, where, "-filter",     "rawTemplate.filter", "LIKE");
+    }
+
+    PXOPT_LOOKUP_BOOL(all, config->args, "-all", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_BOOL(pstamp_order, config->args, "-pstamp_order", false);
+
+
+    psString where2 = NULL;
+    pxmagicAddWhere(config, &where2, "diffRun");
+    pxspaceAddWhere(config, &where2, template ? "rawTemplate" : "rawInput");
+    psString query = pxDataGet("difftool_listrun.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, " WHERE %s", whereClause);
+        psFree(whereClause);
+    } else if (where2) {
+        psStringAppend(&query, " WHERE diffRun.diff_id is not null %s", where2);
+    } else if (!all) {
+        psError(PXTOOLS_ERR_CONFIG, true, "search parameters or -all are required");
+        return false;
+    }
+    psFree(where);
+
+    if (pstamp_order) {
+        if (template) {
+            psStringAppend(&query, " ORDER BY rawTemplate.exp_id, diff_id DESC");
+        } else {
+            psStringAppend(&query, " ORDER BY rawInput.exp_id, diff_id DESC");
+        }
+    }
+            
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "diffRun", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+// a very specfic function to queue a cleaned warpSkyfile to be updated
+static bool setskyfiletoupdateMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(diff_id, config->args, "-diff_id", true, false);
+    PXOPT_LOOKUP_STR(skycell_id, config->args, "-skycell_id", false, false);
+    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
+
+    psString query = pxDataGet("difftool_setskyfiletoupdate.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString setHook = psStringCopy("");
+    if (label) {
+        psStringAppend(&setHook, "\n , diffRun.label = '%s'", label);
+    }
+
+    if (skycell_id) {
+        psStringAppend(&query, " AND (diffSkyfile.skycell_id = '%s')", skycell_id);
+    }
+
+    if (!p_psDBRunQueryF(config->dbh, query, setHook, diff_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(setHook);
+    psFree(query);
+
+    return true;
+}
