a4ec09b5bbfbaf7c4f40053b24f42f075a5b6b85
chmalee
  Tue Nov 12 14:23:32 2024 -0800
Lots of changes after meeting, mostly to accomadate hubtools uploads: allow parentDir in upload request, make batch change dropdowns have the right options. TODO: remove type selection all together from UI, make hub name generation not be hardcoded in ui

diff --git src/hg/lib/userdata.c src/hg/lib/userdata.c
index 3d98b71..4092c0f 100644
--- src/hg/lib/userdata.c
+++ src/hg/lib/userdata.c
@@ -90,100 +90,153 @@
 else
     return NULL;
 }
 
 void addHubSpaceRowForFile(struct hubSpace *row)
 /* We created a file for a user, now add an entry to the hubSpace table for it */
 {
 struct sqlConnection *conn = hConnectCentral();
 
 // now write out row to hubSpace table
 if (!sqlTableExistsOnMain(conn, "hubSpace"))
     {
     errAbort("No hubSpace MySQL table is present. Please send an email to genome-www@soe.ucsc.edu  describing the exact steps you took just before you got this error");
     }
 hubSpaceSaveToDb(conn, row, "hubSpace", 0);
+hDisconnectCentral(&conn);
 }
 
-char *writeHubText(char *path, char *userName, char *encodedHubName, char *hubName, char *db)
+static void makeParentDirRows(char *userName, time_t lastModified, char *db, char *parentDirStr)
+/* For each '/' separated component of parentDirStr, create a row in hubSpace. Return the 
+ * final subdirectory component of parentDirStr */
+{
+int i, slashCount = countChars(parentDirStr, '/');
+char *components[256];
+struct dyString *currLocation = dyStringNew(0);
+int foundSlashes = chopByChar(cloneString(parentDirStr), '/', components, slashCount);
+if (foundSlashes > 256)
+    errAbort("parentDir setting '%s' too long", parentDirStr);
+for (i = 0; i < foundSlashes; i++)
+    {
+    char *subdir = components[i];
+    if (sameString(subdir, "."))
+        continue;
+    fprintf(stderr, "making row for parent dir: '%s'\n", subdir);
+    if (!subdir)
+        errAbort("error: empty subdirectory components for parentDir string '%s'", parentDirStr);
+    struct hubSpace *row = NULL;
+    AllocVar(row);
+    row->userName = userName;
+    row->fileName = subdir;
+    row->fileSize = 0;
+    row->fileType = subdir;
+    row->creationTime = NULL;
+    row->lastModified = sqlUnixTimeToDate(&lastModified, TRUE);
+    row->db = db;
+    row->location = cloneString(dyStringContents(currLocation));
+    row->md5sum = "";
+    row->parentDir = i > 0 ? components[i-1] : "";
+    addHubSpaceRowForFile(row);
+    dyStringAppendC(currLocation, '/');
+    dyStringAppend(currLocation, components[i]);
+    }
+}
+
+char *writeHubText(char *path, char *userName, char *hubName, char *db)
 /* Create a hub.txt file, optionally creating the directory holding it. For convenience, return
  * the file name of the created hub, which can be freed. */
 {
 int oldUmask = 00;
 oldUmask = umask(0);
 makeDirsOnPath(path);
 // restore umask
 umask(oldUmask);
 // now make the hub.txt with some basic information
 char *hubFile = catTwoStrings(path, "/hub.txt");
 FILE *f = mustOpen(hubFile, "w");
 //fprintf(stderr, "would write \"hub %s\nemail %s\nshortLabel %s\nlongLabel %s\nuseOneFile on\n\ngenome %s\n\n\" to %s", hubName, emailForUserName(userName), hubName, hubName, db, hubFile);
 fprintf(f, "hub %s\n"
     "email %s\n"
     "shortLabel %s\n"
     "longLabel %s\n"
     "useOneFile on\n"
     "\n"
     "genome %s\n"
     "\n",
-    encodedHubName, emailForUserName(userName), hubName, hubName, db);
+    hubName, emailForUserName(userName), hubName, hubName, db);
 carefulClose(&f);
 return hubFile;
 }
 
-char *createNewTempHubForUpload(char *requestId, char *userName, char *db, char *trackFileName, char *trackType, char *reqHubName, char *parentDir)
+char *hubNameFromParentDir(char *parentDir)
+/* Assume parentDir does not have leading '/' or '.', parse out the first dir component */
+{
+char *copy = cloneString(parentDir);
+char *firstSlash = strchr(copy, '/');
+if (!firstSlash)
+    {
+    return copy;
+    }
+firstSlash = 0;
+return copy;
+}
+
+void createNewTempHubForUpload(char *requestId, char *userName, char *db, char *trackFileName, char *trackType, char *parentDir)
 /* Creates a hub.txt for this upload with a random hub name. Returns the full path to the hub
- * for convenience. If the reqHubName argument is non-NULL, use that as the hub name instead of
- * a random string AND do not create a hub.txt, only for use from hubtools up command */
+ * for convenience.  */
 {
 char *hubFileName = NULL;
 char *path = NULL;
 struct dyString *hubPath = dyStringNew(0);
-dyStringPrintf(hubPath, "%s%s", getDataDir(userName), reqHubName);
-// the reqHubName was used to make a directory, so it is cgi-encoded and has a '/' at the end
-char *decoded = needMem(strlen(reqHubName));
-cgiDecodeFull(reqHubName, decoded, strlen(reqHubName));
-path = hubFileName = writeHubText(dyStringCannibalize(&hubPath), userName, reqHubName, decoded, db);
+char *hubName = hubNameFromParentDir(parentDir);
+dyStringPrintf(hubPath, "%s%s", getDataDir(userName), hubName);
+fprintf(stderr, "hubPath: %s\n", hubPath->string);
+path = hubFileName = writeHubText(dyStringCannibalize(&hubPath), userName, hubName, db);
 char *encodedTrack = cgiEncodeFull(trackFileName);
-struct dyString *trackFilePath = dyStringCreate("../%s", encodedTrack);
+struct dyString *trackFilePath = dyStringCreate("%s%s%s", parentDir != NULL ? parentDir : "", parentDir != NULL ? "/" : "", encodedTrack);
 FILE *f = mustOpen(hubFileName, "a");
 fprintf(f, "track %s\n"
     "bigDataUrl %s\n"
     "type %s\n"
     "shortLabel %s\n"
     "longLabel %s\n"
     "\n",
     encodedTrack, dyStringCannibalize(&trackFilePath),
     trackType, trackFileName, trackFileName);
 carefulClose(&f);
 
 // we should update the mysql table now with a record of the hub.txt
 struct hubSpace *row = NULL;
 AllocVar(row);
 row->userName = userName;
 row->fileName = "hub.txt";
 row->fileSize = fileSize(hubFileName);
 row->fileType = "hub";
 row->creationTime = NULL;
 time_t lastModTime = fileModTime(hubFileName);
 row->lastModified = sqlUnixTimeToDate(&lastModTime, TRUE);
 row->db = db;
 row->location = path;
 row->md5sum = md5HexForFile(hubFileName);
-row->parentDir = parentDir ? parentDir : "";
+fprintf(stderr, "making parent dir rows\n");
+fflush(stderr);
+makeParentDirRows(userName, lastModTime, db, parentDir);
+row->parentDir = hubName;
+struct dyString *parentsPath = dyStringCreate("%s%s", getDataDir(userName), parentDir);
+fprintf(stderr, "parentDir of hub.txt: '%s'\n", parentsPath->string);
+fflush(stderr);
 addHubSpaceRowForFile(row);
-return reqHubName;
 }
 
 static void deleteHubSpaceRow(char *fname)
 /* Deletes a row from the hubspace table for a given fname */
 {
 struct sqlConnection *conn = hConnectCentral();
 struct dyString *deleteQuery = sqlDyStringCreate("delete from hubSpace where location='%s'", fname);
 sqlUpdate(conn, dyStringCannibalize(&deleteQuery));
 }
 
 void removeFileForUser(char *fname, char *userName)
 /* Remove a file for this user if it exists */
 {
 // The file to remove must be prefixed by the hg.conf userDataDir
 if (!startsWith(getDataDir(userName), fname))
@@ -201,36 +254,30 @@
 /* Remove a hub directory for this user (and all files in the directory), if it exists */
 {
 if (!startsWith(getDataDir(userName), path))
     return;
 if (isDirectory(path))
     {
     struct fileInfo *f, *flist = listDirX(path, NULL, TRUE);
     for (f = flist; f != NULL; f = f->next)
         mustRemove(f->name);
     // now we have deleted all the files in the dir we can safely rmdir
     mustRemove(path);
     deleteHubSpaceRow(path);
     }
 }
 
-void uploadTrack()
-/* Saves a new track to the persistent storage for this user */
-{
-//char *userName = getUserName();
-}
-
 static time_t getFileListLatestTime(struct userFiles *userFiles)
 /* Return the greatest last access time of the files in userFiles->fileList */
 {
 if (!userFiles->fileList)
     errAbort("no files in userFiles->fileList");
 time_t modTime = 0;
 struct fileInfo *f;
 for (f = userFiles->fileList; f != NULL; f = f->next)
     {
     if (f->lastAccess > modTime)
         {
         modTime = f->lastAccess;
         }
     }
 return modTime;