c6d419ecfb6f122d7a0cb99c37f56c32c089bea3 chmalee Thu Jan 22 10:41:38 2026 -0800 HubSpace changes: Allow users to overwrite already uploaded files, but warn them first. When a hub.txt file is being uploaded, don't auto-generate one. Check if the tracks being uploaded already exist in the hub.txt before adding a default stanza for it. Add some more checks in the hook files to prevent faulty uploads. Have the tus client clear localStorage on successful uploads so re-uploads of the same file don't cause confusing errors diff --git src/hg/lib/userdata.c src/hg/lib/userdata.c index 6df0e5f1902..b00694a5e52 100644 --- src/hg/lib/userdata.c +++ src/hg/lib/userdata.c @@ -361,37 +361,80 @@ static char *hubPathFromParentDir(char *parentDir, char *userDataDir) /* Assume parentDir does not have leading '/' or '.', parse out the first dir component * and add it to the users directory*/ { char *copy = cloneString(parentDir); char *firstSlash = strchr(copy, '/'); if (!firstSlash) { return copy; } firstSlash = 0; return catTwoStrings(userDataDir, copy); } +static boolean bigDataUrlExistsInHub(char *hubFileName, char *fileName) +/* Check if a bigDataUrl line already references this file in the hub.txt. + * Simple line-by-line check - not a full trackDb parser. */ +{ +if (!hubFileName || !fileName) + return FALSE; + +struct lineFile *lf = lineFileMayOpen(hubFileName, TRUE); +if (!lf) + return FALSE; + +char *line; +while (lineFileNext(lf, &line, NULL)) + { + char *trimmedLine = skipLeadingSpaces(line); + if (startsWith("bigDataUrl ", trimmedLine)) + { + char *url = trimmedLine + 11; // skip "bigDataUrl " + url = skipLeadingSpaces(url); + if (isEmpty(url)) + continue; + // Check if the URL ends with this filename (handles relative paths) + if (endsWith(url, fileName) || sameString(url, fileName)) + { + lineFileClose(&lf); + return TRUE; + } + } + } +lineFileClose(&lf); +return FALSE; +} + static void writeTrackStanza(char *hubFileName, char *track, char *bigDataUrl, char *type, char *label, char *bigFileLocation) { if ( (sameString(type, "bamIndex") || sameString(type, "tabixIndex") || sameString(type, "text")) ) // don't need to make track stanzas for these supporting files return; +// Skip if this file is already referenced in hub.txt (e.g., user uploaded their own hub.txt) +if (bigDataUrlExistsInHub(hubFileName, bigDataUrl)) + { + fprintf(stderr, "DEBUG: bigDataUrl '%s' already exists in '%s', skipping stanza\n", + bigDataUrl, hubFileName); + return; + } + FILE *f = mustOpen(hubFileName, "a"); +// Always add a leading newline to ensure separation from previous content +fprintf(f, "\n"); char *trackDbType = type; if (sameString(type, "bigBed")) { // don't errAbort if the file is actually not a bigBed struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { // figure out the type based on the bbiFile header struct bbiFile *bbi = bigBedFileOpen(bigFileLocation); char tdbType[32]; safef(tdbType, sizeof(tdbType), "bigBed %d%s", bbi->definedFieldCount, bbi->fieldCount > bbi->definedFieldCount ? " +" : ""); trackDbType = tdbType; bigBedFileClose(&bbi); } errCatchEnd(errCatch);