0bc408820ce1cc3b69dcaa49d72563ea0772b7af
chmalee
  Wed Sep 18 17:04:02 2019 -0700
Making hubClone allow multiple directories in genomes and trackDb file locations, reported by Lou

diff --git src/hg/utils/hubClone/hubClone.c src/hg/utils/hubClone/hubClone.c
index 0f4a762..706cd18 100644
--- src/hg/utils/hubClone/hubClone.c
+++ src/hg/utils/hubClone/hubClone.c
@@ -186,30 +186,53 @@
 
 struct trackHub *readHubFromUrl(char *hubUrl)
 /* readHubUrl: errCatch around trackHubOpen */
 {
 struct trackHub *hub = NULL;
 struct errCatch *errCatch = errCatchNew();
 
 if (errCatchStart(errCatch))
     hub = trackHubOpen(hubUrl, "");
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     errAbort("aborting: %s\n", errCatch->message->string);
 return hub;
 }
 
+FILE *createPathAndFile(char *path)
+/* if path contains parent directories that don't exist, create them first before opening file */
+{
+char *copy = cloneString(path);
+if (stringIn("/", copy))
+    {
+    chopSuffixAt(copy, '/');
+    makeDirs(copy);
+    // now make the real file
+    return mustOpen(path, "w");
+    }
+return mustOpen(path, "w");
+}
+
+void createWriteAndCloseFile(char *fileName, char *url, boolean useOneFile)
+/* Wrapper around a couple lines */
+{
+FILE *f;
+f = createPathAndFile(fileName);
+printOneFile(url, f, useOneFile);
+carefulClose(&f);
+}
+
 void hubClone(char *hubUrl)
 /* hubClone - Clone the hub text files to a local copy, fixing up bigDataUrls 
  * to remote locations if necessary. */
 {
 struct trackHub *hub;
 struct trackHubGenome *genome;
 char *hubBasePath, *hubName, *hubFileName;
 char *genomesUrl, *genomesDir, *genomesFileName;
 char *tdbFileName, *tdbFilePath;
 char *path; 
 FILE *f;
 boolean oneFile = FALSE;
 
 hubBasePath = cloneString(hubUrl);
 chopSuffixAt(hubBasePath, '/'); // don't forget to add a "/" back on!
@@ -226,52 +249,49 @@
 if (trackHubSetting(hub, "useOneFile"))
     {
     oneFile = TRUE;
     makeDirs(hubName);
     path = catTwoStrings(hubName, catTwoStrings("/", hubFileName));
     f = mustOpen(path, "w");
     printOneFile(hubUrl, f, oneFile);
     carefulClose(&f);
     }
 else
     {
     genome = hub->genomeList;
     if (genome == NULL)
         errAbort("error opening %s file", hub->genomesFile);
 
-    makeDirs(hubName);
     path = catTwoStrings(hubName, catTwoStrings("/", hubFileName));
-    f = mustOpen(path, "w");
-    printOneFile(hubUrl, f, oneFile);
-    carefulClose(&f);
+    createWriteAndCloseFile(path, hubUrl, oneFile);
 
     genomesUrl = trackHubRelativeUrl(hub->url, hub->genomesFile);
     genomesFileName = catTwoStrings(hubName, catTwoStrings("/", hub->genomesFile));
-    f = mustOpen(genomesFileName, "w");
-    printOneFile(genomesUrl, f, oneFile);
-    carefulClose(&f);
+    char *genomePath = cloneString(genomesFileName);
+    chopSuffixAt(genomePath, '/'); // used later for making the right directory structure
+
+    createWriteAndCloseFile(genomesFileName, genomesUrl, oneFile);
 
     for (; genome != NULL; genome = genome->next)
         {
         if (startsWith("_", genome->name)) // assembly hubs have a leading '_'
             genome->name += 1;
-        genomesDir = catTwoStrings(hubName, catTwoStrings("/", genome->name));
-        makeDirs(genomesDir);
+
+        // make correct directory strucutre
+        genomesDir = catTwoStrings(genomePath, catTwoStrings("/", genome->name));
         tdbFileName = strrchr(genome->trackDbFile, '/') + 1;
         tdbFilePath = catTwoStrings(genomesDir, catTwoStrings("/", tdbFileName));
-        f = mustOpen(tdbFilePath, "w");
-        printOneFile(genome->trackDbFile, f, oneFile);
-        carefulClose(&f);
+        createWriteAndCloseFile(tdbFilePath, genome->trackDbFile, oneFile);
         }
     }
 }
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 optionInit(&argc, argv, options);
 if (argc != 2)
     usage();
 udcSetDefaultDir(optionVal("udcDir", udcDefaultDir()));
 hubClone(argv[1]);
 return 0;
 }