From 821896f29244bfcf847ac3ee2e8c609fc830e890 Mon Sep 17 00:00:00 2001 From: "Chen, Tai-Lin" Date: Fri, 25 Aug 2023 20:05:28 +0800 Subject: [PATCH] working: update file-graph-algorithm --- packages/file-graph/errors.js | 7 ++ packages/file-graph/file.js | 2 +- packages/file-graph/fileGraph.js | 55 +++++++++---- packages/file-graph/fileGraph.test.js | 110 ++++++++++++++++++++++++++ packages/file-graph/fileNode.js | 24 ++---- 5 files changed, 162 insertions(+), 36 deletions(-) create mode 100644 packages/file-graph/fileGraph.test.js diff --git a/packages/file-graph/errors.js b/packages/file-graph/errors.js index 16539c1..966cd57 100644 --- a/packages/file-graph/errors.js +++ b/packages/file-graph/errors.js @@ -12,3 +12,10 @@ export class ParentNotExistsError extends Error { this.name = 'ParentNotExistsError' } } + +export class FileNotExistsError extends Error { + constructor(message) { + super(message) + this.name = 'FileNotExistsError' + } +} diff --git a/packages/file-graph/file.js b/packages/file-graph/file.js index b7622f5..986e280 100644 --- a/packages/file-graph/file.js +++ b/packages/file-graph/file.js @@ -1,4 +1,4 @@ -import { basename } from './utils' +import { basename } from './utils.js' export default class File { constructor({ path, type, discovered }) { diff --git a/packages/file-graph/fileGraph.js b/packages/file-graph/fileGraph.js index 708d57b..baab3a7 100644 --- a/packages/file-graph/fileGraph.js +++ b/packages/file-graph/fileGraph.js @@ -1,35 +1,54 @@ import FileNode from './fileNode.js' +import { FileNotExistsError } from './errors.js' export default class FileGraph { constructor(root) { this.root = new FileNode(root) } - add(file) { + add(files) { // Logic to add the file node to the graph // You can implement the logic to find the appropriate location in the file graph // If the file node already exists, throw an error - const newNode = new FileNode(file) - this.root.addChild(newNode, { makeParents: true }) + files.forEach((file) => { + this.root.addChild(file, { makeParents: true }) + }) } - remove(file) { + remove(files) { // Logic to remove a file node from the graph // If the file node is a folder, also remove all children // If the file node doesn't exist, throw an error - const nodeToRemove = this.findNode(file) - if (nodeToRemove) { - const parentNode = this.findParentNode(file) - if (parentNode) { - parentNode.children = parentNode.children.filter( - (child) => child !== nodeToRemove + files.forEach((file) => { + const pathFolders = file.path + .split('/') + .filter((folder) => folder.length > 0) + const fileName = pathFolders.pop() + let currentNode = this.root + + for (const folder of pathFolders) { + currentNode = currentNode.children.find( + (child) => child.name === folder + ) + if (!currentNode) { + throw new FileNotExistsError( + `File not found: ${fileToFind.path}, ${this.toString()}` + ) + } + } + + if (!currentNode.children.some((child) => child.name === fileName)) { + throw new FileNotExistsError( + `File not found: ${file.path}, ${this.toString()}` + ) + } else { + currentNode.children = currentNode.children.filter( + (child) => child.name !== fileName ) } - } else { - throw new Error(`File node not found: ${file.path}`) - } + }) } discover(eventFiles) { @@ -37,13 +56,17 @@ export default class FileGraph { // Overwrite the file graph with the provided files // Remove file nodes that don't exist anymore and add new ones - const updatedNodes = eventFiles.map((file) => new FileNode(file)) - this.root = new FileNode({ + const newRoot = new FileNode({ path: '/', type: 'folder', discovered: true, - children: updatedNodes, }) + + eventFiles.forEach((file) => { + newRoot.addChild(file, { makeParents: true }) + }) + + this.root = newRoot } handleEvent(event) { diff --git a/packages/file-graph/fileGraph.test.js b/packages/file-graph/fileGraph.test.js new file mode 100644 index 0000000..97ab912 --- /dev/null +++ b/packages/file-graph/fileGraph.test.js @@ -0,0 +1,110 @@ +import FileGraph from './fileGraph.js' +import FileNode from './fileNode.js' + +describe('FileGraph', () => { + let root + + beforeEach(() => { + root = new FileNode({ + path: '/', + type: 'folder', + discovered: true, + }) + }) + + test('add files to graph', () => { + const fileGraph = new FileGraph(root) + + const filesToAdd = [ + { + path: '/home/user/file1.txt', + type: 'file', + discovered: true, + }, + { + path: '/home/user/folder1', + type: 'folder', + discovered: true, + }, + ] + + fileGraph.add(filesToAdd) + + console.log(fileGraph.root.toString()) + expect(fileGraph.root.children.length).toBe(1) + expect(fileGraph.root.children[0].children[0].children.length).toBe(2) + }) + + test('remove files from graph', () => { + const fileGraph = new FileGraph(root) + + const filesToAdd = [ + { + path: '/home/user/file1.txt', + type: 'file', + discovered: true, + }, + { + path: '/home/user/folder1', + type: 'folder', + discovered: true, + }, + ] + + fileGraph.add(filesToAdd) + + const filesToRemove = [ + { + path: '/home/user/folder1', + type: 'folder', + }, + ] + + fileGraph.remove(filesToRemove) + + console.log(fileGraph.root.toString()) + expect(fileGraph.root.children[0].children[0].children.length).toBe(1) + }) + + test('discover new files', () => { + const fileGraph = new FileGraph(root) + + const filesToAdd = [ + { + path: '/home/user/file1.txt', + type: 'file', + discovered: true, + }, + { + path: '/home/user/folder1', + type: 'folder', + discovered: true, + }, + ] + + fileGraph.add(filesToAdd) + expect(fileGraph.root.children[0].children[0].children.length).toBe(2) + + const newFiles = [ + { + path: '/home/newfile.txt', + type: 'file', + discovered: true, + }, + { + path: '/home/user/file1.txt', + type: 'file', + discovered: true, + }, + ] + + fileGraph.discover(newFiles) + + console.log(fileGraph.root.toString()) + expect(fileGraph.root.children[0].children.length).toBe(2) + expect(fileGraph.root.children[0].children[0].name).toBe('newfile.txt') + expect(fileGraph.root.children[0].children[0].children[0].name).toBe( + 'file1.txt' + ) + }) +}) diff --git a/packages/file-graph/fileNode.js b/packages/file-graph/fileNode.js index d0c9874..1529976 100644 --- a/packages/file-graph/fileNode.js +++ b/packages/file-graph/fileNode.js @@ -1,5 +1,9 @@ import File from './file.js' -import { DuplicateItemError, ParentNotExistsError } from './errors.js' +import { + DuplicateItemError, + ParentNotExistsError, + FileNotExistsError, +} from './errors.js' import { basename, dirname } from './utils.js' export default class FileNode extends File { @@ -92,22 +96,4 @@ export default class FileNode extends File { .join('') return `${indent}${this.name}${suffix}\n${childrenString}` } - - findNode(fileToFind) { - const pathFolders = fileToFind.path - .split('/') - .filter((folder) => folder.length > 0) - let currentNode = this - - for (const folder of pathFolders) { - currentNode = currentNode.children.find( - (child) => child.name === folder && child.type === 'folder' - ) - if (!currentNode) { - return null - } - } - - return currentNode - } }