373b5c4187422a9584814dcfa324028fd2e50f14 chmalee Tue Aug 4 15:00:30 2026 -0700 Have the pre-finish hook return the rows it wrote, and fix the table display bugs that the real row data now lets us resolve, refs #37999 Co-Authored-By: Claude Opus 5 (1M context) diff --git src/hg/hgHubConnect/hooks/pre-finish.c src/hg/hgHubConnect/hooks/pre-finish.c index a414861b735..4443d1810c2 100644 --- src/hg/hgHubConnect/hooks/pre-finish.c +++ src/hg/hgHubConnect/hooks/pre-finish.c @@ -247,36 +247,59 @@ upgradeExistingHubToAssembly(row, userDataDir, encodedParentDir); } else createNewTempHubForUpload(reqId, row, userDataDir); } else if (isTwoBit) { // user's hub.txt is authoritative; just flip rows to assemblyHub. upgradeExistingHubToAssembly(row, userDataDir, encodedParentDir); } } // still under the hub lock: makeParentDirRows checks for a row and then // inserts it, so two uploads to one hub would otherwise both insert the // same directory row // first make the parentDir rows - makeParentDirRows(row->userName, sqlDateToUnixTime(row->lastModified), row->db, row->parentDir, userDataDir, row->hubType); + // the directory rows carry the upload's own timestamp. row->lastModified + // holds it as a GMT clock string, which sqlDateToUnixTime would read as + // local time, so pass the seconds directly + makeParentDirRows(row->userName, lastModified, row->db, row->parentDir, userDataDir, row->hubType); row->parentDir = encodedParentDir ? hubNameFromPath(encodedParentDir) : ""; addHubSpaceRowForFile(row); unlockHubDir(hubLockFd); fprintf(stderr, "added hubSpace row for file '%s'\n", fileName); fflush(stderr); + + // Send the client the hub as it now stands, so it can show the new file, + // its directories and the hub.txt. The upload has already succeeded at + // this point, so catch errors here rather than let them reject it: the + // worst case is a client that shows nothing new until the page is reloaded + struct errCatch *respCatch = errCatchNew(0); + if (errCatchStart(respCatch)) + { + if (encodedParentDir) + { + char *hubName = hubRootFromParentDir(encodedParentDir); + setUploadedFileList(response, userName, listFilesInHubDir(userName, hubName)); + freeMem(hubName); + } + } + errCatchEnd(respCatch); + if (respCatch->gotError) + fprintf(stderr, "could not list hub for response: %s\n", + respCatch->message->string); + errCatchFree(&respCatch); } } // pop the handlers before handling the error, the cleanup below can itself // errAbort, which would longjmp back into this same block errCatchEnd(errCatch); if (errCatch->gotError) { // App-level reject: exit 0 + RejectUpload=true is the tusd protocol for // forwarding HTTPResponse verbatim. Non-zero gets wrapped. rejectUpload(response, "%s", errCatch->message->string); // clear the partial upload so the user can try again. pre-create hands tusd a // ChangeFileInfo, so tusFile is the file in the user's directory, not a temp // copy, and tusInfo is tusd's .info alongside it. remove() rather than // mustRemove(): this is the error path, and an abort here exits before the // response is printed, leaving the client with a bare 500 instead of the