Index: src/hg/lib/customTrack.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/lib/customTrack.c,v
retrieving revision 1.178
retrieving revision 1.179
diff -b -B -U 4 -r1.178 -r1.179
--- src/hg/lib/customTrack.c	28 Sep 2009 18:19:31 -0000	1.178
+++ src/hg/lib/customTrack.c	9 Dec 2009 19:27:06 -0000	1.179
@@ -343,9 +343,9 @@
 /* add new tracks to the custom track list, removing older versions,
  * and saving the replaced tracks in a list for the caller */
 {
 struct hash *ctHash = hashNew(5);
-struct customTrack *newCtList = NULL, *replacedCts = NULL;
+struct customTrack *newCtList = NULL, *oldCtList = NULL, *replacedCts = NULL;
 struct customTrack *ct = NULL, *nextCt = NULL;
 
 /* determine next sequence number for default tracks */
 nextUniqueDefaultTrack(ctList);
@@ -361,9 +361,9 @@
     else
         {
         if (isDefaultTrack(ct) && makeDefaultUnique)
             makeUniqueDefaultTrack(ct);
-        slAddTail(&newCtList, ct);
+        slAddHead(&newCtList, ct);
         hashAdd(ctHash, ct->tdb->tableName, ct);
         }
     }
 /* add in older tracks that haven't been replaced by newer */
@@ -372,22 +372,67 @@
     struct customTrack *newCt;
     nextCt = ct->next;
     if ((newCt = hashFindVal(ctHash, ct->tdb->tableName)) != NULL)
         {
-        slAddTail(&replacedCts, ct);
+        slAddHead(&replacedCts, ct);
         }
     else
         {
-        slAddTail(&newCtList, ct);
+        slAddHead(&oldCtList, ct);
         hashAdd(ctHash, ct->tdb->tableName, ct);
         }
     }
+slReverse(&oldCtList);
+slReverse(&replacedCts);
+newCtList = slCat(newCtList, oldCtList);
 hashFree(&ctHash);
 if (retReplacedCts)
     *retReplacedCts = replacedCts;
 return newCtList;
 }
 
+
+
+struct customTrack *customTrackRemoveUnavailableFromList(struct customTrack *ctList)
+/* Remove from list unavailable remote resources.
+ * This must be done after the custom-track bed file has been saved. */
+{
+struct customTrack *newCtList = NULL, *ct = NULL, *nextCt = NULL;
+
+/* Remove from list unavailable remote resources. */
+for (ct = ctList; ct != NULL; ct = nextCt)
+    {
+    nextCt = ct->next;
+    if (!ct->networkErrMsg)
+        {
+        slAddHead(&newCtList, ct);
+        }
+    }
+slReverse(&newCtList);
+return newCtList;
+}
+
+char *customTrackUnavailableErrsFromList(struct customTrack *ctList)
+/* Find network errors of unavailable remote resources from list. */
+{
+struct customTrack *ct = NULL;
+struct dyString *ds = dyStringNew(0);
+char *sep = "";
+for (ct = ctList; ct != NULL; ct = ct->next)
+    {
+    if (ct->networkErrMsg)
+	{
+	dyStringPrintf(ds, "%s%s", sep, ct->networkErrMsg);
+	sep = "<br>\n";
+	}
+    }
+char *result = dyStringCannibalize(&ds);
+if (sameOk(result,""))
+    result = NULL;
+return result;
+}
+
+
 char *customTrackFileVar(char *database)
 /* return CGI var name containing custom track filename for a database */
 {
 char buf[64];
@@ -731,8 +776,14 @@
             }
         else
             err = msg;
         }
+    else
+	{
+	err = customTrackUnavailableErrsFromList(newCts);
+	if (err)
+	    newCts = NULL;  /* do not save the unhappy remote cts*/
+	}
     errCatchFree(&errCatch);
     }
 
 /* the 'ctfile_$db' variable contains a filename from the trash directory.
@@ -818,8 +869,14 @@
         }
 if (newCts || removedCt || changedCt || ctConfigUpdate(ctFileName))
     customTracksSaveCart(genomeDb, cart, ctList);
 
+if (!endsWith(cgiScriptName(),"hgCustom"))
+    {
+    /* filter out cts that are unavailable remote resources */
+    ctList = customTrackRemoveUnavailableFromList(ctList);
+    }
+
 cartRemove(cart, CT_CUSTOM_TEXT_ALT_VAR);
 cartRemove(cart, CT_CUSTOM_TEXT_VAR);
 cartRemove(cart, CT_CUSTOM_FILE_VAR);
 cartRemove(cart, CT_CUSTOM_FILE_NAME_VAR);

