c11b5a4152074f716254867f3de4fd020e602c26
hiram
  Mon May 1 13:06:03 2023 -0700
handling errors from failed rsync command refs #23589

diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c
index 7553e65..d3345f0 100644
--- src/hg/hubApi/list.c
+++ src/hg/hubApi/list.c
@@ -590,30 +590,34 @@
  *   returning total bytes in the files listing
  */
 {
 long long totalBytes = 0;
 if (*itemsDone >= maxItemsOutput)
     return totalBytes;
 boolean reachedMaxItems = FALSE;
 int index = 3;	/* rsyncCmd[3] == starts out at NULL, will become the
                  *    hgdownload path */
 char *rsyncCmd[] = {"/usr/bin/rsync", "-a", "--list-only", NULL, NULL};
 /* rsyncCmd[4] will remain NULL to terminate the list */
 
 struct dyString *tmpDy = dyStringNew(128);
 dyStringPrintf(tmpDy, "%s::%s/%s/", DOWNLOAD_HOST, downPath, db);
 rsyncCmd[index++] = dyStringCannibalize(&tmpDy);
+
+struct errCatch *errCatch = errCatchNew();
+if (errCatchStart(errCatch))
+    {
     struct pipeline *dataPipe = pipelineOpen1(rsyncCmd,
        pipelineRead, "/dev/null", NULL, 0);
     FILE *readingLines = pipelineFile(dataPipe);
     char lineBuf[PATH_MAX + 1024];
     while (! reachedMaxItems && fgets(lineBuf, sizeof(lineBuf), readingLines) != NULL)
         {
         if (startsWith("d", lineBuf))
             continue;
         *itemsDone += 1;
         if (*itemsDone > maxItemsOutput)
             {
             reachedMaxItems = TRUE;
             }
         else
             {
@@ -630,30 +634,37 @@
                 textLineOut(outString);
                 }
             else
                 {
                 jsonWriteObjectStart(jw, NULL);
                 jsonWriteNumber(jw, "sizeBytes", sqlLongLong(columns[1]));
                safef(outString, sizeof(outString), "%sT%s", columns[2], columns[3]);
                 jsonWriteString(jw, "dateTime", outString);
           safef(outString, sizeof(outString), "%s/%s/%s", downPath, db, columns[4]);
                 jsonWriteString(jw, "url", outString);
                 jsonWriteObjectEnd(jw);
                 }
             }
         }
     pipelineClose(&dataPipe);
+    }
+errCatchEnd(errCatch);
+if (errCatch->gotError)
+    {
+    apiErrAbort(err400, err400Msg, "can not find genome='%s' for endpoint '/list/files'", db);
+    }
+errCatchFree(&errCatch);
 return totalBytes;
 }
 
 static void filesJsonOutput(FILE *f, char *genome, boolean textOut)
 /* for given genome, output the URLs to files available on hgdownload
  *   can be a UCSC database genome, or a GenArk hub genome name
  */
 {
 long long itemsReturned = 0;
 boolean genArkHub = FALSE;
 char genArkUrl[PATH_MAX + 1024];
 
 if ( isGenArk(genome) )
     {
     genArkHub = TRUE;
@@ -1130,31 +1141,31 @@
 	{
         schemaJsonOutput(stdout, db, track);
 	return;
 	}
     else
 	{
         hubSchemaJsonOutput(stdout, hubUrl, genome, track);
 	return;
 	}
     }
 else if (sameWord("files", words[1]))
     {
     boolean textOut = FALSE;
     char *extraArgs = verifyLegalArgs(argListFiles);
     if (extraArgs)
-	apiErrAbort(err400, err400Msg, "extraneous arguments found for function /list/files '%s', only 'genome' is allowed.", extraArgs);
+	apiErrAbort(err400, err400Msg, "extraneous arguments found for function /list/files '%s', only 'genome' and 'format' is allowed.", extraArgs);
 
     char *genome = cgiOptionalString("genome");
     char *format = cgiOptionalString("format");
     if (isEmpty(genome))
         apiErrAbort(err400, err400Msg, "must supply a genome name for endpoint '/list/files' (a database name or GenArk genome name, e.g.: 'hg38' or 'GCA_021951015.1'");
     if (isNotEmpty(format))
 	{
 	if (sameWord("text", format))
 	    textOut = TRUE;
         else
 	    apiErrAbort(err400, err400Msg, "only format=text allowed for endpoint '/list/files', found: format=%s", format);
 	}
     filesJsonOutput(stdout, genome, textOut);
     }
 else