84b2a66056c61f0661676de79e7d710073ba8d5d max Tue Feb 3 01:37:38 2026 -0800 adding hub email display to hub error output, refs #36916 and refs #33571 diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c index 426b0a9c360..20a4459b34d 100644 --- src/hg/hgTracks/hgTracks.c +++ src/hg/hgTracks/hgTracks.c @@ -1200,35 +1200,39 @@ char *(*finder)(char *needle, char *haystack) = (anyIupac(fOligo) ? iupacIn : stringInWrapper); int oligoSize = strlen(fOligo); char *rOligo = cloneString(fOligo); char *rMatch = NULL, *fMatch = NULL; struct bed *bedList = NULL, *bed; char strand; int count = 0, maxCount = 1000000; char *strandFilter = cartUsualString(cart, oligoMatchStrandVar, oligoMatchStrandDefault); boolean searchForward = sameString(strandFilter, "both") || sameString(strandFilter, "forward"); boolean searchReverse = sameString(strandFilter, "both") || sameString(strandFilter, "reverse"); if (oligoSize >= 2) { if (searchForward) fMatch = finder(fOligo, dna); - iupacReverseComplement(rOligo, oligoSize); + if (sameString(rOligo, fOligo)) rOligo = NULL; else if (searchReverse) + { + iupacReverseComplement(rOligo, oligoSize); rMatch = finder(rOligo, dna); + } + for (;;) { char *oneMatch = NULL; if (rMatch == NULL) { if (fMatch == NULL) break; else { oneMatch = fMatch; fMatch = finder(fOligo, fMatch+1); strand = '+'; } } else if (fMatch == NULL) @@ -8747,30 +8751,61 @@ #endif unsigned getParaLoadTimeout() // get the parallel load timeout in seconds (defaults to 90) { char *paraLoadTimeoutStr = cartOptionalString(cart, "parallelFetch.timeout"); if (paraLoadTimeoutStr == NULL) paraLoadTimeoutStr = cfgOptionDefault("parallelFetch.timeout", "90"); // wait up to default 90 seconds. unsigned paraLoadTimeout = sqlUnsigned(paraLoadTimeoutStr); return paraLoadTimeout; } +static char *hubPublicEmailFromHubName(char *hubName) +{ +/* return public hub email given url or NULL if such a column doesn't exist (mirrors don't have this column) */ +/* result must be freed */ +char *hubIdStr = strchr(hubName, '_'); // could not find a function for this in hubConnect.c +if (!hubIdStr) + return NULL; +unsigned hubId = sqlUnsigned(hubIdStr+1); + +struct hubConnectStatus *hubStatus = hubFromIdNoAbort(hubId); +if (hubStatus == NULL) + return NULL; + +char *url = hubStatus->hubUrl; +if (!url) + return NULL; + +struct sqlConnection *conn = hConnectCentral(); + +char *email = NULL; +if (sqlColumnExists(conn, "hubPublic", "email")) + { + char query[1000]; + sqlSafef(query, sizeof query, "SELECT email FROM hubPublic WHERE hubUrl='%s'", url); + email = sqlQuickNonemptyString(conn, query); + } + +hDisconnectCentral(&conn); +return email; +} + void doTrackForm(char *psOutput, struct tempName *ideoTn) /* Make the tracks display form with the zoom/scroll buttons and the active * image. If the ideoTn parameter is not NULL, it is filled in if the * ideogram is created. */ { #ifdef GRAPH_BUTTON_ON_QUICKLIFT int graphCount = 0; #endif int disconCount = 0; struct group *group; struct track *track; char *freezeName = NULL; boolean hideAll = cgiVarExists("hgt.hideAll"); boolean hideTracks = cgiOptionalString( "hideTracks") != NULL; boolean defaultTracks = cgiVarExists("hgt.reset"); @@ -9901,30 +9936,33 @@ // we want tracks in the visible list to also be visible // in the normal group list, so use a separate hash for the // visible tracks grouping groupTrackListAddSuper(cart, group, hashNew(8), hashNew(8)); } else groupTrackListAddSuper(cart, group, superHash, trackHash); /* Display track controls */ if (group->errMessage) { hPrintf("Track hub error "); printInfoIcon("Use the hub debugging tool under My Data > Track Hubs > Hub Development. You need to switch off File caching there to see your changes without delay. Error Response is missing required header usually means the hub is not reachable.

Contact us or the hub provider if you cannot resolve the issue."); hPrintf(": "); hPrintf("%s", group->errMessage); + char *email = hubPublicEmailFromHubName(hubName); + if (isNotEmpty(email)) + hPrintf("
You can contact the hub author at %s", email); hPrintf("\n"); } for (tr = group->trackList; tr != NULL; tr = tr->next) { struct track *track = tr->track; if (tdbIsSuperTrackChild(track->tdb)) /* don't display supertrack members */ continue; // only top level tracks contribute to the total count trackCount++; myControlGridStartCell(cg, isOpen, group->name, shouldBreakAll(track->shortLabel)); printTrackLink(track);