diff --git a/src/client/handlers/VaultsSecretsGetFileTree.ts b/src/client/handlers/VaultsSecretsGetFileTree.ts index d39bf89b4..758f6c01f 100644 --- a/src/client/handlers/VaultsSecretsGetFileTree.ts +++ b/src/client/handlers/VaultsSecretsGetFileTree.ts @@ -2,10 +2,8 @@ import type { DB } from '@matrixai/db'; import type VaultManager from '../../vaults/VaultManager'; import type { ClientRPCRequestParams, ClientRPCResponseResult } from '../types'; import type { SecretFilesMessage, VaultFileNode } from '../types'; -import path from 'path'; import { ServerHandler } from '@matrixai/rpc'; -import { generateStats } from '../../vaults/fileTree'; -import { StatEncoded } from '../../vaults/types'; +import { globWalk } from '../../vaults/fileTree'; import * as vaultsUtils from '../../vaults/utils'; import * as vaultsErrors from '../../vaults/errors'; import * as clientErrors from '../errors'; @@ -40,42 +38,36 @@ class VaultsSecretsGetFileTree extends ServerHandler< void, void > { - try { - // @ts-ignore: While the types don't fully match, it matches enough for our usage. - let files: Array = await fs.promises.readdir(input.pattern); - files = files.map((file) => path.join(input.pattern, file)); + const fileTreeGen = globWalk({ + fs: fs, + basePath: '.', + pattern: input.pattern, + yieldParents: false, + yieldDirectories: true, + yieldFiles: true, + yieldStats: input.yieldStats, + }); - for await (const file of files) { - try { - const stat = await fs.promises.lstat(file); - const type = stat.isFile() ? 'FILE' : 'DIRECTORY'; - let stats: StatEncoded | undefined; - - if (input.yieldStats) { - stats = generateStats(stat); - if (stats.isSymbolicLink) { - // @ts-ignore: Again, the types don't fully match, but it works. - stats.symbolicLinkTarget = await fs.promises.readlink(file); - } - } else { - stats = undefined; - } - yield { - path: file, - type: type, - stat: stats, - }; - } catch (e) { - throw new clientErrors.ErrorClientFSReadFailed( - `Failed to read file: ${file}`, - { cause: e }, - ); - } + let hasResults = false; + for await (const file of fileTreeGen) { + hasResults = true; + if (file.stat?.isSymbolicLink) { + // @ts-ignore: The types match enough to make it work. + file.stat.symbolicLinkTarget = await fs.promises.readlink( + file.path, + ); } - } catch (e) { + + yield { + path: file.path, + type: file.type, + stat: file.stat, + }; + } + + if (!hasResults) { throw new clientErrors.ErrorClientFSReadFailed( - `Failed to read directory: ${input.pattern}`, - { cause: e }, + `No matches exist for pattern: ${input.pattern}`, ); } }); diff --git a/src/vaults/fileTree.ts b/src/vaults/fileTree.ts index 697e37484..5595b35d3 100644 --- a/src/vaults/fileTree.ts +++ b/src/vaults/fileTree.ts @@ -113,7 +113,7 @@ async function* globWalk({ // `.` and `./` will not partially match the pattern, so we exclude the initial path // We're doing a partial match to skip directories that can't contain our pattern if ( - !minimatch(currentPath, patternPath, { partial: true }) && + !minimatch(currentPath, patternPath, { partial: true, dot: true }) && currentPath !== basePathNormalised ) { current = queue.shift(); @@ -141,7 +141,7 @@ async function* globWalk({ }); } // Wildcards can find directories so we need yield them too - if (!minimatch(currentPath, patternPath)) { + if (!minimatch(currentPath, patternPath, { dot: true })) { current = queue.shift(); continue; } @@ -163,7 +163,7 @@ async function* globWalk({ } } else if (stat.isFile()) { // Check if the file matches the pattern - if (!minimatch(currentPath, patternPath)) { + if (!minimatch(currentPath, patternPath, { dot: true })) { current = queue.shift(); continue; }