404d5bb6d8c0418d5f06535ef470e36c35d2a237
chmalee
  Thu Apr 16 15:57:56 2026 -0700
Add assembly hub support to hubSpace.

Users can upload a .2bit to create an assembly hub, optionally alongside
their own *.hub.txt (prefix names like araTha1.hub.txt are recognized)
and sibling track files. Uploads run in parallel; hub.txt mutations are
serialized per-hub via flock so arrival order does not matter.

- hubSpace table gains a hubType column ('trackHub' or 'assemblyHub');
ON DUPLICATE KEY UPDATE excludes it so a re-upload cannot revert an
upgraded hub.
- writeHubText can now emit an assembly stanza derived from the 2bit;
upgradeHubTxtForAssembly promotes an existing plain hub.txt in place
when a 2bit arrives after tracks.
- pre-finish decides synthesize vs upgrade vs leave-alone from server
state (existing rows, hub.txt on disk) plus a single client flag
(batchHasHubTxt); client-supplied hubType is no longer trusted.
- Client UI adds 2bit as a file type, locks the genome field when the
hub is authoritative (drilled-in or batch hub.txt), defaults new
uploads to an existing assembly hub at top level, and routes
hgTracks URLs through 'genome=' vs 'db=' by hubType.
- Fix pre-existing nested-path bug in hubPathFromParentDir
(*firstSlash = 0).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

diff --git src/hg/inc/hubSpace.h src/hg/inc/hubSpace.h
index 8134a5f59c3..8a693bea72b 100644
--- src/hg/inc/hubSpace.h
+++ src/hg/inc/hubSpace.h
@@ -1,41 +1,42 @@
 /* hubSpace.h was originally generated by the autoSql program, which also
  * generated hubSpace.c and hubSpace.sql.  This header links the database and
  * the RAM representation of objects. */
 
 #ifndef HUBSPACE_H
 #define HUBSPACE_H
 
 #include "jksql.h"
-#define HUBSPACE_NUM_COLS 10
+#define HUBSPACE_NUM_COLS 11
 
 extern char *hubSpaceCommaSepFieldNames;
 
 struct hubSpace
 /* file storage table for users to store uploaded tracks */
     {
     struct hubSpace *next;  /* Next in singly linked list. */
     char *userName;	/* userName of user uploading file */
     char *fileName;	/* name of uploaded files. The actual path to this file is different */
     long long fileSize;	/* size of the uploaded file */
     char *fileType;	/* track type of file */
     char *creationTime;	/* first upload time */
     char *lastModified;	/* last change time */
     char *db;	/* genome assembly associated with this file */
     char *location;	/* file system path or URL to file */
     char *md5sum;	/* md5sum of file */
     char *parentDir;	/* parent directory of file */
+    char *hubType;	/* type of hub this file belongs to: trackHub or assemblyHub */
     };
 
 void hubSpaceStaticLoad(char **row, struct hubSpace *ret);
 /* Load a row from hubSpace table into ret.  The contents of ret will
  * be replaced at the next call to this function. */
 
 struct hubSpace *hubSpaceLoadByQuery(struct sqlConnection *conn, char *query);
 /* Load all hubSpace from table that satisfy the query given.
  * Where query is of the form 'select * from example where something=something'
  * or 'select example.* from example, anotherTable where example.something =
  * anotherTable.something'.
  * Dispose of this with hubSpaceFreeList(). */
 
 void hubSpaceSaveToDb(struct sqlConnection *conn, struct hubSpace *el, char *tableName, int updateSize);
 /* Save hubSpace as a row to the table specified by tableName.