f48fc325d72424177878c4849096c77e06c2d3b0
max
  Mon Aug 17 07:34:42 2026 -0700
BLAT results: own track group, Delete-all button, clearer names, refs #38086

Behind hg.conf blatResultsGroup (default off, a release gate):

- BLAT result custom tracks go into their own "BLAT Results" track group
instead of the generic Custom Tracks group.
- That group's header gets a "Delete all" button that removes every BLAT
result track at once, so users are not stuck deleting them one by one.
- Headerless queries are named by query size + the top hit's gene, e.g.
"360bp SOD1", instead of the useless "blat YourSeq"; the date goes in
the longLabel.

hgBlat.c       getCustomName naming + blatDateStamp/topHitLocusLabel helpers
hgc.c          buildBigPsl tags the results track group=blat
customFactory.c checkGroup accepts the synthetic "blat" group
hgTracks.c     synthesize the BLAT Results group; Delete-all button; keep
the per-track delete icon for the new group
hgTracks.js    deleteAllBlatTracks()
hgCustom.c     hgct_do_delete_blat action (removes all blatResult=on tracks)
hgConfCatalog.py  register blatResultsGroup as a release gate

diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index af977e9af58..8f9d8dd4998 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -27496,37 +27496,41 @@
 {
 char *trackName = cartString(cart, "trackName");
 char *trackDescription = cartString(cart, "trackDescription");
 char *pslName, *faName, *qName;
 parseSs(fileNames, &pslName, &faName, &qName);
 
 struct tempName bigBedTn;
 trashDirDateFile(&bigBedTn, "hgBlat", "bp", ".bb");
 char *bigBedFile = bigBedTn.forCgi;
 makeBigPsl(pslName, faName, database, bigBedFile);
 
 char* host = getenv("HTTP_HOST");
 
 boolean isProt = cgiOptionalString("isProt") != NULL;
 // blatResult=on tags this as a BLAT results track so previous ones can be found (see blatOldTracks).
-char *customTextTemplate = "track type=bigPsl blatResult=on indelDoubleInsert=on indelQueryInsert=on pslFile=%s visibility=pack showAll=on htmlUrl=http://%s/goldenPath/help/hgUserPsl.html %s bigDataUrl=%s name=\"%s\" description=\"%s\" colorByStrand=\"0,0,0 0,0,150\" mouseOver=\"${oChromStart}-${oChromEnd} of ${oChromSize} bp, strand ${oStrand}\"\n";
+// group=blat (gated by hg.conf blatResultsGroup) puts BLAT results in their own "BLAT Results" track
+// group instead of Custom Tracks, so they are easy to find and clear as a set (see the group's
+// "Delete all" button in hgTracks).
+char *groupTag = cfgOptionBooleanDefault("blatResultsGroup", FALSE) ? "group=blat " : "";
+char *customTextTemplate = "track type=bigPsl blatResult=on %sindelDoubleInsert=on indelQueryInsert=on pslFile=%s visibility=pack showAll=on htmlUrl=http://%s/goldenPath/help/hgUserPsl.html %s bigDataUrl=%s name=\"%s\" description=\"%s\" colorByStrand=\"0,0,0 0,0,150\" mouseOver=\"${oChromStart}-${oChromEnd} of ${oChromSize} bp, strand ${oStrand}\"\n";
 char *extraForMismatch = "indelPolyA=on showDiffBasesAllScales=. baseColorUseSequence=lfExtra baseColorDefault=diffBases";
 
 if (isProt)
     extraForMismatch = "";
 char buffer[4096];
-safef(buffer, sizeof buffer, customTextTemplate, bigBedTn.forCgi, host, extraForMismatch, bigBedTn.forCgi, trackName, trackDescription);
+safef(buffer, sizeof buffer, customTextTemplate, groupTag, bigBedTn.forCgi, host, extraForMismatch, bigBedTn.forCgi, trackName, trackDescription);
 
 struct customTrack *ctList = getCtList();
 struct customTrack *newCts = customFactoryParse(database, buffer, FALSE, NULL, NULL);
 
 /* Optionally clear PREVIOUS BLAT result tracks (those tagged blatResult=on) so the user is not
  * confused about which results are current.  hg.conf "blatOldTracks":
  *   keep   (default) - do nothing, every search's track stays as-is
  *   hide             - leave earlier BLAT tracks in the session but set them to hide
  *   delete           - remove earlier BLAT tracks from the session (their trash files age out)
  * Only BLAT-tagged tracks are touched; the track just made is left alone. */
 char *oldTracks = cfgOptionDefault("blatOldTracks", "keep");
 /* Fail safe on an unrecognized value (e.g. a typo in hg.conf): fall back to "keep" rather than to
  * the destructive "delete" branch below, so a misconfiguration never silently discards a user's
  * previous BLAT tracks. */
 if (differentString(oldTracks, "keep") && differentString(oldTracks, "hide")