d05963670ee4c6b2b54366dc284d32e2b7896356 hiram Fri Aug 14 09:22:16 2026 -0700 candidate for patch fixing automatic redirect from GCA to GCF assemblies for track or assembly hubs refs #38082 diff --git src/hg/lib/hubConnect.c src/hg/lib/hubConnect.c index a5874268b06..567bf75da9f 100644 --- src/hg/lib/hubConnect.c +++ src/hg/lib/hubConnect.c @@ -1126,93 +1126,130 @@ static unsigned lookForUndecoratedDb(char *name) // Look for this undecorated in the attached assembly hubs { struct trackHubGenome *genome = trackHubGetGenomeUndecorated(name); if (genome == NULL) return FALSE; struct trackHub *trackHub = genome->trackHub; if ((trackHub != NULL) && (trackHub->hubStatus != NULL)) return trackHub->hubStatus->id; return 0; } +static unsigned lookForGenarkHub(struct sqlConnection *conn, struct cart *cart, char *genarkPrefix, char *name, boolean *added) +// See if genark hosts an assembly hub for this accession; if so attach it +// and return its hub id (0 if genark doesn't have it, or the attach failed). +{ +char query[4096]; +char buffer[4096]; +sqlSafef(query, sizeof query, "select hubUrl from %s where gcAccession='%s'", genarkTableName(), name); +if (sqlQuickQuery(conn, query, buffer, sizeof buffer)) + { + char url[4096]; + safef(url, sizeof url, "%s/%s", genarkPrefix, buffer); + + struct hubConnectStatus *status = getAndSetHubStatus( cart, url, TRUE); + + if (status) + { + *added = TRUE; + return status->id; + } + } +return 0; +} + static boolean lookForLonelyHubs(struct cart *cart, struct hubConnectStatus *hubList, char **newDatabase, char *genarkPrefix) // We go through the hubs and see if any of them reference an assembly // that is NOT currently loaded, but we know a URL to load it. { struct sqlConnection *conn = hConnectCentral(); if (!sqlTableExists(conn, genarkTableName())) return FALSE; boolean added = FALSE; struct hubConnectStatus *hub; for(hub = hubList; hub; hub = hub->next) { struct trackHub *tHub = hub->trackHub; if (tHub == NULL) continue; struct trackHubGenome *genomeList = tHub->genomeList, *genome; for(genome = genomeList; genome; genome = genome->next) { char *name = genome->name; - name = asmAliasFind(name); - if (!hDbIsActive(name) ) - { + // a non-NULL twoBitPath means this genome carries its own sequence, + // i.e. it's a real assembly hub, not just a track hub naming an + // assembly it expects to find hosted elsewhere. Its own declared + // GCA/GCF accession is what should be displayed -- don't redirect it + // to a different, merely "equivalent" hub via asmAlias. + if (genome->twoBitPath != NULL) + continue; + + char *aliasName = asmAliasFind(name); + + // if the assembly is already active under its alias (a classic + // database, or a hub already attached under that name), there's + // nothing more to do + if (hDbIsActive(aliasName)) + continue; + char buffer[4096]; unsigned newId = 0; - // look with undecorated name for an attached assembly hub + // Prefer keeping the hub on the accession exactly as the hub author + // declared it: only fall back to an asmAlias-equivalent accession + // if the declared one isn't available anywhere -- not already + // attached, and genark doesn't host it either. + char *targetName = name; if (!(newId = lookForUndecoratedDb(name))) - { - // see if genark has this assembly - char query[4096]; - sqlSafef(query, sizeof query, "select hubUrl from %s where gcAccession='%s'", genarkTableName(), name); - if (sqlQuickQuery(conn, query, buffer, sizeof buffer)) - { - char url[4096]; - safef(url, sizeof url, "%s/%s", genarkPrefix, buffer); + newId = lookForGenarkHub(conn, cart, genarkPrefix, name, &added); - struct hubConnectStatus *status = getAndSetHubStatus( cart, url, TRUE); - - if (status) + if (!newId && differentString(aliasName, name)) { - newId = status->id; - added = TRUE; - } - } + targetName = aliasName; + if (!(newId = lookForUndecoratedDb(aliasName))) + newId = lookForGenarkHub(conn, cart, genarkPrefix, aliasName, &added); } // if we found an id, change some names to use it as a decoration if (newId) { - safef(buffer, sizeof buffer, "hub_%d_%s", newId, name); + safef(buffer, sizeof buffer, "hub_%d_%s", newId, targetName); genome->name = cloneString(buffer); - // if our new database is an undecorated db, decorate it - if (*newDatabase && sameString(*newDatabase, name)) + // genome was registered in tHub->genomeHash under its original + // name when the hub was parsed; trackHubFindGenome() looks + // genomes up by name through that hash, so re-register it under + // its new name now that we've renamed it in place, the same way + // hubConnectStatusForIdExt() does for quickLifted hubs. + hashAdd(tHub->genomeHash, genome->name, genome); + hashAdd(tHub->genomeHash, hubConnectSkipHubPrefix(genome->name), genome); + + // if our new database is an undecorated db (either as the hub + // author declared it, or its asmAlias-equivalent form), decorate it + if (*newDatabase && (sameString(*newDatabase, name) || sameString(*newDatabase, aliasName))) *newDatabase = cloneString(buffer); } - - } } } hDisconnectCentral(&conn); return added; } static char *getCuratedHubPrefix() /* figure out what sandbox we're in. */ { char *curatedHubPrefix = cfgOption("curatedHubPrefix"); if (isEmpty(curatedHubPrefix)) curatedHubPrefix = "public"; return curatedHubPrefix;