diff --git a/src/command/repo/ls.c b/src/command/repo/ls.c index 61ee3f3cb..f8e03c808 100644 --- a/src/command/repo/ls.c +++ b/src/command/repo/ls.c @@ -37,8 +37,8 @@ storageListRenderCallback(void *data, const StorageInfo *info) StorageListRenderCallbackData *listData = (StorageListRenderCallbackData *)data; - // Skip . path when output is text - if (info->type == storageTypePath && strEq(info->name, DOT_STR) && !listData->json) + // Skip . path if it is not first when json output + if (info->type == storageTypePath && strEq(info->name, DOT_STR) && (!listData->first || !listData->json)) { FUNCTION_TEST_RETURN_VOID(); return; @@ -150,9 +150,26 @@ storageListRender(IoWrite *write) if (data.json) ioWrite(data.write, BRACEL_BUF); - storageInfoListP( - storageRepo(), path, storageListRenderCallback, &data, .sortOrder = sortOrder, .expression = cfgOptionStr(cfgOptFilter), - .recurse = cfgOptionBool(cfgOptRecurse)); + // Check if this is a file + StorageInfo info = storageInfoP(storageRepo(), path, .ignoreMissing = true); + + if (info.exists && info.type == storageTypeFile) + { + info.name = DOT_STR; + storageListRenderCallback(&data, &info); + } + // Else try to list the path + else + { + // The path will always be reported as existing so we don't get different results from storage that does not support paths + if (data.json) + storageListRenderCallback(&data, &(StorageInfo){.type = storageTypePath, .name = DOT_STR}); + + // List content of the path + storageInfoListP( + storageRepo(), path, storageListRenderCallback, &data, .sortOrder = sortOrder, .expression = cfgOptionStr(cfgOptFilter), + .recurse = cfgOptionBool(cfgOptRecurse)); + } if (data.json) ioWrite(data.write, BRACER_BUF); diff --git a/test/src/module/command/repoTest.c b/test/src/module/command/repoTest.c index 6a45a20d7..10b0bf0fe 100644 --- a/test/src/module/command/repoTest.c +++ b/test/src/module/command/repoTest.c @@ -37,7 +37,12 @@ testRun(void) output = bufNew(0); cfgOptionSet(cfgOptOutput, cfgSourceParam, VARSTRDEF("json")); TEST_RESULT_VOID(storageListRender(ioBufferWriteNew(output)), "missing directory (json)"); - TEST_RESULT_STR_Z(strNewBuf(output), "{}", " check output"); + TEST_RESULT_STR_Z( + strNewBuf(output), + "{" + "\".\":{\"type\":\"path\"}" + "}", + " check output"); // Empty directory // ------------------------------------------------------------------------------------------------------------------------- @@ -76,7 +81,7 @@ testRun(void) output = bufNew(0); cfgOptionSet(cfgOptOutput, cfgSourceParam, VARSTRDEF("json")); - TEST_RESULT_VOID(storageListRender(ioBufferWriteNew(output)), "path and file (text)"); + TEST_RESULT_VOID(storageListRender(ioBufferWriteNew(output)), "path and file (json)"); TEST_RESULT_STR_Z( strNewBuf(output), "{" @@ -150,6 +155,21 @@ testRun(void) output = bufNew(0); TEST_ERROR(storageListRender(ioBufferWriteNew(output)), ParamInvalidError, "only one path may be specified"); + + // File + // ------------------------------------------------------------------------------------------------------------------------- + argList = strLstNew(); + strLstAdd(argList, strNewFmt("--repo-path=%s/repo/aaa", testPath())); + strLstAddZ(argList, "--output=json"); + harnessCfgLoad(cfgCmdRepoLs, argList); + + TEST_RESULT_VOID(storageListRender(ioBufferWriteNew(output)), "file (json)"); + TEST_RESULT_STR_Z( + strNewBuf(output), + "{" + "\".\":{\"type\":\"file\",\"size\":8,\"time\":1578671569}" + "}", + " check output"); } FUNCTION_HARNESS_RESULT_VOID();