diff --git a/src/services/db/GitFileSystemService.ts b/src/services/db/GitFileSystemService.ts index e81c20bf9..ea7ca8d42 100644 --- a/src/services/db/GitFileSystemService.ts +++ b/src/services/db/GitFileSystemService.ts @@ -319,7 +319,7 @@ export default class GitFileSystemService { repoName: string, filePath: string, isStaging: boolean - ): ResultAsync { + ): ResultAsync { const efsVolPath = isStaging ? EFS_VOL_PATH_STAGING : EFS_VOL_PATH_STAGING_LITE @@ -333,6 +333,14 @@ export default class GitFileSystemService { ) if (error instanceof GitError) { + // NOTE: While some path can be potentially normalised by Git (eg. images//path.png), + // it is not guaranteed to exist in HEAD. We simply return a not found error in this case. + if ( + error.message.includes("fatal: path") && + error.message.includes("exists on disk, but not in 'HEAD'") + ) { + return new NotFoundError("File/Directory does not exist") + } return new GitFileSystemError("Unable to determine Git blob hash") } @@ -1121,7 +1129,11 @@ export default class GitFileSystemService { ) ) .andThen((directoryContents) => { - const resultAsyncs = directoryContents.map((directoryItem) => { + const IGNORED_FILES = [".git"] + const filteredDirectoryContents = directoryContents.filter( + (directoryItem) => !IGNORED_FILES.includes(directoryItem.name) + ) + const resultAsyncs = filteredDirectoryContents.map((directoryItem) => { const isDirectory = directoryItem.isDirectory() const { name } = directoryItem const path = directoryPath === "" ? name : `${directoryPath}/${name}` diff --git a/src/services/db/__tests__/GitFileSystemService.spec.ts b/src/services/db/__tests__/GitFileSystemService.spec.ts index c829879dc..f23d80192 100644 --- a/src/services/db/__tests__/GitFileSystemService.spec.ts +++ b/src/services/db/__tests__/GitFileSystemService.spec.ts @@ -56,6 +56,11 @@ const dirTree = { }, } +const dirTreeWithIgnoredFiles = { + ...dirTree, + ".git": "fake git directory", +} + describe("GitFileSystemService", () => { beforeEach(() => { mockFs({ @@ -172,6 +177,18 @@ describe("GitFileSystemService", () => { expect(result._unsafeUnwrapErr()).toBeInstanceOf(NotFoundError) }) + + it("should ignore .git folder", async () => { + mockFs({ + [EFS_VOL_PATH_STAGING]: dirTreeWithIgnoredFiles, + }) + const result = await GitFileSystemService.listDirectoryContents( + "fake-repo", + "fake-empty-dir", + DEFAULT_BRANCH + ) + expect(result._unsafeUnwrap()).toHaveLength(0) + }) }) describe("listPaginatedDirectoryContents", () => { @@ -661,6 +678,26 @@ describe("GitFileSystemService", () => { expect(result._unsafeUnwrapErr()).toBeInstanceOf(GitFileSystemError) }) + + it("should return not found error for a non-existent file", async () => { + MockSimpleGit.cwd.mockReturnValueOnce({ + revparse: jest + .fn() + .mockRejectedValueOnce( + new GitError( + undefined, + `fatal: path //fake-media-file.png exists on disk, but not in 'HEAD'` + ) + ), + }) + const result = await GitFileSystemService.getGitBlobHash( + "fake-repo", + "fake-dir/%2ffake-media-file.png", + true + ) + + expect(result._unsafeUnwrapErr()).toBeInstanceOf(NotFoundError) + }) }) describe("getFilePathStats", () => {