Merge pull request #3452 from github/robertbrignull/findDirWithFile
Move findDirWithFile to files.ts
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user