Move findDirWithFile to files.ts

This commit is contained in:
Robert
2024-03-07 12:38:47 +00:00
parent 8b2355acc3
commit fe6dc8a7a3
4 changed files with 88 additions and 90 deletions

View File

@@ -176,3 +176,32 @@ export function findCommonParentDir(...paths: string[]): string {
function isTopLevelPath(path: string): boolean {
return dirname(path) === path;
}
/**
* Recursively looks for a file in a directory. If the file exists, then returns the directory containing the file.
*
* @param dir The directory to search
* @param toFind The file to recursively look for in this directory
*
* @returns the directory containing the file, or undefined if not found.
*/
export async function findDirWithFile(
dir: string,
...toFind: string[]
): Promise<string | undefined> {
if (!(await stat(dir)).isDirectory()) {
return;
}
const files = await readdir(dir);
if (toFind.some((file) => files.includes(file))) {
return dir;
}
for (const file of files) {
const newPath = join(dir, file);
const result = await findDirWithFile(newPath, ...toFind);
if (result) {
return result;
}
}
return;
}

View File

@@ -10,8 +10,6 @@ import {
pathExists,
createWriteStream,
remove,
stat,
readdir,
} from "fs-extra";
import { basename, join } from "path";
import type { Octokit } from "@octokit/rest";
@@ -39,6 +37,7 @@ import { getLanguageDisplayName } from "../common/query-language";
import type { DatabaseOrigin } from "./local-databases/database-origin";
import { createTimeoutSignal } from "../common/fetch-stream";
import type { App } from "../common/app";
import { findDirWithFile } from "../common/files";
/**
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
@@ -588,36 +587,6 @@ function isFile(databaseUrl: string) {
return Uri.parse(databaseUrl).scheme === "file";
}
/**
* Recursively looks for a file in a directory. If the file exists, then returns the directory containing the file.
*
* @param dir The directory to search
* @param toFind The file to recursively look for in this directory
*
* @returns the directory containing the file, or undefined if not found.
*/
// exported for testing
export async function findDirWithFile(
dir: string,
...toFind: string[]
): Promise<string | undefined> {
if (!(await stat(dir)).isDirectory()) {
return;
}
const files = await readdir(dir);
if (toFind.some((file) => files.includes(file))) {
return dir;
}
for (const file of files) {
const newPath = join(dir, file);
const result = await findDirWithFile(newPath, ...toFind);
if (result) {
return result;
}
}
return;
}
export async function convertGithubNwoToDatabaseUrl(
nwo: string,
octokit: Octokit,

View File

@@ -3,6 +3,7 @@ import { join, parse } from "path";
import {
containsPath,
findCommonParentDir,
findDirWithFile,
gatherQlFiles,
getDirectoryNamesInsidePath,
pathsEqual,
@@ -11,7 +12,13 @@ import {
} from "../../../src/common/files";
import type { DirResult } from "tmp";
import { dirSync } from "tmp";
import { ensureDirSync, symlinkSync, writeFileSync } from "fs-extra";
import {
createFileSync,
ensureDirSync,
mkdirSync,
symlinkSync,
writeFileSync,
} from "fs-extra";
import "../../matchers/toEqualPath";
describe("files", () => {
@@ -592,3 +599,52 @@ describe("findCommonParentDir", () => {
expect(commonDir).toEqualPath(dataDir);
});
});
describe("findDirWithFile", () => {
let dir: DirResult;
beforeEach(() => {
dir = dirSync({ unsafeCleanup: true });
createFile("a");
createFile("b");
createFile("c");
createDir("dir1");
createFile("dir1", "d");
createFile("dir1", "e");
createFile("dir1", "f");
createDir("dir2");
createFile("dir2", "g");
createFile("dir2", "h");
createFile("dir2", "i");
createDir("dir2", "dir3");
createFile("dir2", "dir3", "j");
createFile("dir2", "dir3", "k");
createFile("dir2", "dir3", "l");
});
it("should find files", async () => {
expect(await findDirWithFile(dir.name, "k")).toBe(
join(dir.name, "dir2", "dir3"),
);
expect(await findDirWithFile(dir.name, "h")).toBe(join(dir.name, "dir2"));
expect(await findDirWithFile(dir.name, "z", "a")).toBe(dir.name);
// there's some slight indeterminism when more than one name exists
// but in general, this will find files in the current directory before
// finding files in sub-dirs
expect(await findDirWithFile(dir.name, "k", "a")).toBe(dir.name);
});
it("should not find files", async () => {
expect(await findDirWithFile(dir.name, "x", "y", "z")).toBeUndefined();
});
function createFile(...segments: string[]) {
createFileSync(join(dir.name, ...segments));
}
function createDir(...segments: string[]) {
mkdirSync(join(dir.name, ...segments));
}
});

View File

@@ -1,13 +1,6 @@
import { join } from "path";
import { createFileSync, mkdirSync } from "fs-extra";
import type { DirResult } from "tmp";
import { dirSync } from "tmp";
import { window } from "vscode";
import {
convertGithubNwoToDatabaseUrl,
findDirWithFile,
} from "../../../../src/databases/database-fetcher";
import { convertGithubNwoToDatabaseUrl } from "../../../../src/databases/database-fetcher";
import type { Octokit } from "@octokit/rest";
import {
mockedObject,
@@ -201,53 +194,4 @@ describe("database-fetcher", () => {
});
});
});
describe("findDirWithFile", () => {
let dir: DirResult;
beforeEach(() => {
dir = dirSync({ unsafeCleanup: true });
createFile("a");
createFile("b");
createFile("c");
createDir("dir1");
createFile("dir1", "d");
createFile("dir1", "e");
createFile("dir1", "f");
createDir("dir2");
createFile("dir2", "g");
createFile("dir2", "h");
createFile("dir2", "i");
createDir("dir2", "dir3");
createFile("dir2", "dir3", "j");
createFile("dir2", "dir3", "k");
createFile("dir2", "dir3", "l");
});
it("should find files", async () => {
expect(await findDirWithFile(dir.name, "k")).toBe(
join(dir.name, "dir2", "dir3"),
);
expect(await findDirWithFile(dir.name, "h")).toBe(join(dir.name, "dir2"));
expect(await findDirWithFile(dir.name, "z", "a")).toBe(dir.name);
// there's some slight indeterminism when more than one name exists
// but in general, this will find files in the current directory before
// finding files in sub-dirs
expect(await findDirWithFile(dir.name, "k", "a")).toBe(dir.name);
});
it("should not find files", async () => {
expect(await findDirWithFile(dir.name, "x", "y", "z")).toBeUndefined();
});
function createFile(...segments: string[]) {
createFileSync(join(dir.name, ...segments));
}
function createDir(...segments: string[]) {
mkdirSync(join(dir.name, ...segments));
}
});
});