From dda3f42dddd9f8e9068ef251bc08ae355869ddcc Mon Sep 17 00:00:00 2001 From: kim5566 <28945404+kim5566@users.noreply.github.com> Date: Fri, 18 Feb 2022 07:02:46 +1100 Subject: [PATCH] updated to config as func Signed-off-by: kim5566 <28945404+kim5566@users.noreply.github.com> --- .changeset/mean-pumpkins-search.md | 22 ++++- plugins/todo-backend/api-report.md | 1 + .../src/lib/TodoReader/TodoScmReader.test.ts | 80 ++++++++++++------- .../src/lib/TodoReader/TodoScmReader.ts | 18 +++-- 4 files changed, 85 insertions(+), 36 deletions(-) diff --git a/.changeset/mean-pumpkins-search.md b/.changeset/mean-pumpkins-search.md index 78a92ff5eb..ddaea98b9e 100644 --- a/.changeset/mean-pumpkins-search.md +++ b/.changeset/mean-pumpkins-search.md @@ -2,4 +2,24 @@ '@backstage/plugin-todo-backend': patch --- -Add support to exclude vendor folder in `todo` plugin. +Add support to exclude certain folders in `todo` plugin. + +You can add function by configuring your own exclusion logic, for example: + +```ts +import { + TodoScmReader, + createTodoParser, +} from '@backstage/plugin-todo-backend'; + +// ... + +const todoReader = TodoScmReader.fromConfig(config, { + logger, + reader, + filePathFilter: (filePath: string): boolean => { + ... + YOUR LOGIC HERE + }, +}); +``` diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index ac8b2ce957..84ebc88299 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -131,6 +131,7 @@ export type TodoScmReaderOptions = { reader: UrlReader; integrations: ScmIntegrations; parser?: TodoParser; + filePathFilter?: (path: string) => boolean; }; // @public (undocumented) diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts index 0036e748ff..1ca836162e 100644 --- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts +++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.test.ts @@ -190,23 +190,18 @@ describe('TodoScmReader', () => { ); }); - it('should filter out exclude folders', async () => { + it('should not filter out exclude folders', async () => { const reader = mockReader(); + const filePathFilter = jest.fn(() => true); + const todoReader = new TodoScmReader({ logger: getVoidLogger(), reader, integrations: ScmIntegrations.fromConfig(new ConfigReader({})), + filePathFilter, }); reader.readTree.mockResolvedValueOnce({ files: async () => [ - { - content: async () => Buffer.from('// TODO: my-todo', 'utf8'), - path: 'vendor/another-file.go', - }, - { - content: async () => Buffer.from('// TODO: my-todo', 'utf8'), - path: 'test/vendor/another-file.go', - }, { content: async () => Buffer.from('// TODO: my-todo', 'utf8'), path: 'my-folder/my-file.js', @@ -219,22 +214,6 @@ describe('TodoScmReader', () => { }), ).resolves.toEqual({ items: [ - { - text: 'my-todo', - tag: 'TODO', - lineNumber: 1, - repoFilePath: 'vendor/another-file.go', - viewUrl: - 'https://github.com/backstage/backstage/vendor/another-file.go#L1', - }, - { - text: 'my-todo', - tag: 'TODO', - lineNumber: 1, - repoFilePath: 'test/vendor/another-file.go', - viewUrl: - 'https://github.com/backstage/backstage/test/vendor/another-file.go#L1', - }, { text: 'my-todo', tag: 'TODO', @@ -255,10 +234,55 @@ describe('TodoScmReader', () => { ); // Filter function should filter out exclude folders const filterFunc = reader.readTree.mock.calls[0][1]!.filter!; - expect(filterFunc('another-file.go')).toBe(true); - expect(filterFunc('vendor/another-file.go')).toBe(false); - expect(filterFunc('test/vendor/another-file.go')).toBe(false); expect(filterFunc('my-file.js')).toBe(true); expect(filterFunc('my-folder/my-file.js')).toBe(true); }); + + it('should filter out exclude folders', async () => { + const reader = mockReader(); + const filePathFilter = jest.fn(() => false); + + const todoReader = new TodoScmReader({ + logger: getVoidLogger(), + reader, + integrations: ScmIntegrations.fromConfig(new ConfigReader({})), + filePathFilter, + }); + reader.readTree.mockResolvedValueOnce({ + files: async () => [ + { + content: async () => Buffer.from('// TODO: my-todo', 'utf8'), + path: 'my-folder/my-file.js', + }, + ], + } as ReadTreeResponse); + await expect( + todoReader.readTodos({ + url: 'https://github.com/backstage/backstage/catalog-info.yaml', + }), + ).resolves.toEqual({ + items: [ + { + text: 'my-todo', + tag: 'TODO', + lineNumber: 1, + repoFilePath: 'my-folder/my-file.js', + viewUrl: + 'https://github.com/backstage/backstage/my-folder/my-file.js#L1', + }, + ], + }); + expect(reader.readTree).toHaveBeenCalledTimes(1); + expect(reader.readTree).toHaveBeenCalledWith( + 'https://github.com/backstage/backstage/catalog-info.yaml', + { + etag: undefined, + filter: expect.any(Function), + }, + ); + // Filter function should filter out exclude folders + const filterFunc = reader.readTree.mock.calls[0][1]!.filter!; + expect(filterFunc('my-file.js')).toBe(false); + expect(filterFunc('my-folder/my-file.js')).toBe(false); + }); }); diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts index ade15343d5..9514a8a2cf 100644 --- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts +++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts @@ -41,14 +41,13 @@ const excludedExtensions = [ ]; const MAX_FILE_SIZE = 200000; -const excludeFolders = ['vendor']; - /** @public */ export type TodoScmReaderOptions = { logger: Logger; reader: UrlReader; integrations: ScmIntegrations; parser?: TodoParser; + filePathFilter?: (filePath: string) => boolean; }; type CacheItem = { @@ -62,6 +61,7 @@ export class TodoScmReader implements TodoReader { private readonly reader: UrlReader; private readonly parser: TodoParser; private readonly integrations: ScmIntegrations; + private readonly filePathFilter: (filePath: string) => boolean; private readonly cache = new Map(); private readonly inFlightReads = new Map>(); @@ -81,6 +81,7 @@ export class TodoScmReader implements TodoReader { this.reader = options.reader; this.parser = options.parser ?? createTodoParser(); this.integrations = options.integrations; + this.filePathFilter = options.filePathFilter ?? (() => true); } async readTodos(options: ReadTodosOptions): Promise { @@ -91,7 +92,12 @@ export class TodoScmReader implements TodoReader { } const cacheItem = this.cache.get(url); - const newRead = this.doReadTodos({ url }, cacheItem?.etag).catch(error => { + const filePathFilter = this.filePathFilter; + const newRead = this.doReadTodos( + { url }, + filePathFilter, + cacheItem?.etag, + ).catch(error => { if (cacheItem && error.name === 'NotModifiedError') { return cacheItem; } @@ -110,13 +116,11 @@ export class TodoScmReader implements TodoReader { private async doReadTodos( options: ReadTodosOptions, + filePathFilter: (filePath: string) => boolean, etag?: string, ): Promise { const { url } = options; - const filePathFilter = (filePath: string): boolean => { - const splitPath = filePath.split('/'); - return !excludeFolders.some(r => splitPath.includes(r)); - }; + const tree = await this.reader.readTree(url, { etag, filter(filePath, info) {