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/hgHubConnect/hooks/pre-create.c src/hg/hgHubConnect/hooks/pre-create.c
index 08dcaf05702..f9036839edc 100644
--- src/hg/hgHubConnect/hooks/pre-create.c
+++ src/hg/hgHubConnect/hooks/pre-create.c
@@ -75,59 +75,73 @@
             // maybe an apiKey was provided, use that instead to look up the userName
             char *apiKey = jsonQueryString(req, "", "Event.Upload.MetaData.apiKey", NULL);
             if (!apiKey)
                 {
                 errAbort("You are not logged in. Please navigate to My Data -> My Sessions and log in or create an account.");
                 }
             else
                 {
                 userName = userNameForApiKey(NULL, apiKey);
                 if (!userName)
                     errAbort("You are not logged in. Please navigate to My Data -> My Sessions and log in or create an account.");
                 }
             }
         fprintf(stderr, "userName='%s'\n'", userName);
         long reqFileSize = jsonQueryInt(req, "", "Event.Upload.Size", 0, NULL);
+        // Check multiple possible metadata keys for filename (Uppy sends 'filename' and 'name' by default,
+        // our JS code also sets 'fileName' - try all to handle resumed uploads with old metadata)
         char *reqFileName = jsonQueryString(req, "", "Event.Upload.MetaData.fileName", NULL);
+        if (!reqFileName)
+            reqFileName = jsonQueryString(req, "", "Event.Upload.MetaData.filename", NULL);
+        if (!reqFileName)
+            reqFileName = jsonQueryString(req, "", "Event.Upload.MetaData.name", NULL);
+        if (!reqFileName)
+            {
+            errAbort("No filename found in upload metadata (checked fileName, filename, and name)");
+            }
         char *reqParentDir = jsonQueryString(req, "", "Event.Upload.MetaData.parentDir", NULL);
         boolean isHubToolsUpload = FALSE;
         char *hubtoolsStr = jsonQueryString(req, "", "Event.Upload.MetaData.hubtools", NULL);
         if (hubtoolsStr)
             isHubToolsUpload = sameString(hubtoolsStr, "TRUE") || sameString(hubtoolsStr, "true");
+        // Check for allowOverwrite metadata from JavaScript (for hub.txt overwrites)
+        char *allowOverwriteStr = jsonQueryString(req, "", "Event.Upload.MetaData.allowOverwrite", NULL);
+        boolean allowOverwrite = (allowOverwriteStr && (sameString(allowOverwriteStr, "TRUE") || sameString(allowOverwriteStr, "true")));
+        boolean forceOverwrite = isHubToolsUpload || allowOverwrite;
         long currQuota = checkUserQuota(userName);
         long newQuota = currQuota + reqFileSize;
         long maxQuota = getMaxUserQuota(userName);
         if (newQuota > maxQuota)
             {
             errAbort("File '%s' is too large, need %s free space but current used space is %s out of %s", reqFileName, prettyFileSize(reqFileSize), prettyFileSize(currQuota), prettyFileSize(maxQuota));
             }
         char *reqFileType = jsonQueryString(req, "", "Event.Upload.MetaData.fileType", NULL);
         if (!isFileTypeRecognized(reqFileType))
             {
             errAbort("File type '%s' for file '%s' is not accepted at this time", reqFileType, reqFileName);
             }
         char *reqGenome = jsonQueryString(req, "", "Event.Upload.MetaData.genome", NULL);
         if (!reqGenome)
             {
             errAbort("Genome selection is NULL for file '%s' is invalid. Please choose the correct genome", reqFileName);
             }
 
         // we've passed all the checks so we can return that we are good to upload the file
         if (exitStatus == 0)
             {
             // set the location of the upload to the location it will ultimately live
-            char *location = setUploadPath(userName, reqFileName, reqParentDir, isHubToolsUpload);
+            char *location = setUploadPath(userName, reqFileName, reqParentDir, forceOverwrite);
             if (!location)
                 {
                 errAbort("Error setting upload path in pre-create for file '%s'. This is an"
                         " issue with our server, please email genome-www@soe.ucsc.edu with your"
                         " userName so we can investigate.", reqFileName);
                 }
             struct hash *changeObjHash = hashNew(0);
             struct hash *pathObjHash = hashNew(0);
             struct jsonElement *changeObj = newJsonObject(changeObjHash);
             struct jsonElement *pathObj = newJsonObject(pathObjHash);
 
             jsonObjectAdd(pathObj, "Path", newJsonString(location));
             jsonObjectAdd(changeObj, "Storage", pathObj);
             jsonObjectAdd(changeObj, "ID", newJsonString(makeRandomKey(128)));
             jsonObjectAdd(response, "ChangeFileInfo", changeObj);