544b4db19ee0f7f92c9d338d6900c34a53d9f032 chmalee Wed Jun 11 15:45:15 2025 -0700 Add back the good parts of b318572799b35, mostly have the pre-create hook set the upload path so we don't have to move files around in the pre-finish hook diff --git src/hg/hgHubConnect/hooks/hooklib.c src/hg/hgHubConnect/hooks/hooklib.c index c008cda925c..b0d40b7300b 100644 --- src/hg/hgHubConnect/hooks/hooklib.c +++ src/hg/hgHubConnect/hooks/hooklib.c @@ -39,38 +39,90 @@ int i = 0; for (; i < numChops; i++) { // we can ignore .. and . in paths, it is an error if hubtools is creating these names // don't errAbort right now because hubtools does send things like 'hubName/.' // as a parentDir, but that should be fixed soon if (sameString(pathArr[i], ".") || sameString(pathArr[i], "..")) { continue; } dyStringPrintf(ret, "%s/", cgiEncodeFull(pathArr[i])); } return dyStringCannibalize(&ret); } -void fillOutHttpResponseError() +char *setUploadPath(char *userName, char *fileName, char *parentDir, boolean forceOverwrite) +/* return the path, relative to hg.conf tusdDataDir, where we will store this upload + * ensures all subdirectories on the final path will exist, and then returns + * userPrefix/userName/parentDir/fileName + * NOTE: This must be a relative path or tusd will complain */ +{ +char *dataDir = getDataDir(userName); +struct dyString *fullFilePath = dyStringNew(0); +struct dyString *retPath = dyStringNew(0); +// if parentDir provided we are throwing the files in there +if (parentDir) + { + char *encodedParentDir = encodePath(parentDir); + if (!endsWith(encodedParentDir, "/")) + encodedParentDir = catTwoStrings(encodedParentDir, "/"); + dataDir = catTwoStrings(dataDir, encodedParentDir); + } +dyStringPrintf(fullFilePath, "%s%s", dataDir, fileName); + +fprintf(stderr, "DEBUG: setUploadPath of '%s' to '%s'\n", fileName, dyStringContents(fullFilePath)); +// TODO: check if file exists or not and let user choose to overwrite +// and re-call this hook, for now just exit if the file exists +// hubtools uploads always overwrite because we assume those users +// know what they are doing +if (fileExists(dyStringContents(fullFilePath)) && !forceOverwrite) + { + errAbort("file '%s' exists already, not overwriting", dyStringContents(fullFilePath)); + } +else + { + // since we are returning a ChangeFileInfo response in pre-create, tusd will write + // the uploaded file into the users directory for us, ensure the subdirs exist + int oldUmask = 00; + if (!isDirectory(dataDir)) + { + fprintf(stderr, "making directory '%s'\n", dataDir); + // the directory needs to be 777 for apache, ignore umask for now + oldUmask = umask(0); + makeDirsOnPath(dataDir); + // restore umask + umask(oldUmask); + } + // now we can construct the path relative to tusd uploadDir + dyStringPrintf(retPath, "%s/%s/%s", getEncodedUserNamePath(userName), parentDir, fileName); + return dyStringCannibalize(&retPath); + } +// on error return NULL +return NULL; +} + +void fillOutHttpResponseError(struct jsonElement *response) { fprintf(stderr, "http response error!\n"); } -void fillOutHttpResponseSuccess() +void fillOutHttpResponseSuccess(struct jsonElement *response) { fprintf(stderr, "http response success!\n"); +// DEBUG: comment out after a few releases +jsonPrintToFile(response, NULL, stderr, 0); } struct jsonElement *makeDefaultResponse() /* Create the default response json with some fields pre-filled */ { struct hash *defHash = hashNew(0); struct jsonElement *response = newJsonObject(defHash); // only the HTTP Response object is important to have by default, the other // fields will be created as needed struct jsonElement *httpResponse = newJsonObject(hashNew(0)); jsonObjectAdd(httpResponse, HTTP_STATUS, newJsonNumber(200)); // default to a successful response jsonObjectAdd(httpResponse, HTTP_BODY, newJsonString("")); struct jsonElement *header = newJsonObject(hashNew(0)); jsonObjectAdd(header, HTTP_CONTENT_TYPE, newJsonString(HTTP_CONTENT_TYPE_STR)); jsonObjectAdd(httpResponse, HTTP_HEADER, header);