mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
working: update file-graph-algorithm
This commit is contained in:
1 parent
ab570e9c1b
commit
821896f292
5 files changed
+162
-36
No files matched your search
@@ -12,3 +12,10 @@ export class ParentNotExistsError extends Error {
|
|||||||
this.name = 'ParentNotExistsError'
|
this.name = 'ParentNotExistsError'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FileNotExistsError extends Error {
|
||||||
|
constructor(message) {
|
||||||
|
super(message)
|
||||||
|
this.name = 'FileNotExistsError'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { basename } from './utils'
|
import { basename } from './utils.js'
|
||||||
|
|
||||||
export default class File {
|
export default class File {
|
||||||
constructor({ path, type, discovered }) {
|
constructor({ path, type, discovered }) {
|
||||||
|
|||||||
@@ -1,35 +1,54 @@
|
|||||||
import FileNode from './fileNode.js'
|
import FileNode from './fileNode.js'
|
||||||
|
import { FileNotExistsError } from './errors.js'
|
||||||
|
|
||||||
export default class FileGraph {
|
export default class FileGraph {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
this.root = new FileNode(root)
|
this.root = new FileNode(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
add(file) {
|
add(files) {
|
||||||
// Logic to add the file node to the graph
|
// Logic to add the file node to the graph
|
||||||
// You can implement the logic to find the appropriate location in the file graph
|
// You can implement the logic to find the appropriate location in the file graph
|
||||||
// If the file node already exists, throw an error
|
// If the file node already exists, throw an error
|
||||||
|
|
||||||
const newNode = new FileNode(file)
|
files.forEach((file) => {
|
||||||
this.root.addChild(newNode, { makeParents: true })
|
this.root.addChild(file, { makeParents: true })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(file) {
|
remove(files) {
|
||||||
// Logic to remove a file node from the graph
|
// Logic to remove a file node from the graph
|
||||||
// If the file node is a folder, also remove all children
|
// If the file node is a folder, also remove all children
|
||||||
// If the file node doesn't exist, throw an error
|
// If the file node doesn't exist, throw an error
|
||||||
|
|
||||||
const nodeToRemove = this.findNode(file)
|
files.forEach((file) => {
|
||||||
if (nodeToRemove) {
|
const pathFolders = file.path
|
||||||
const parentNode = this.findParentNode(file)
|
.split('/')
|
||||||
if (parentNode) {
|
.filter((folder) => folder.length > 0)
|
||||||
parentNode.children = parentNode.children.filter(
|
const fileName = pathFolders.pop()
|
||||||
(child) => child !== nodeToRemove
|
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) {
|
discover(eventFiles) {
|
||||||
@@ -37,13 +56,17 @@ export default class FileGraph {
|
|||||||
// Overwrite the file graph with the provided files
|
// Overwrite the file graph with the provided files
|
||||||
// Remove file nodes that don't exist anymore and add new ones
|
// Remove file nodes that don't exist anymore and add new ones
|
||||||
|
|
||||||
const updatedNodes = eventFiles.map((file) => new FileNode(file))
|
const newRoot = new FileNode({
|
||||||
this.root = new FileNode({
|
|
||||||
path: '/',
|
path: '/',
|
||||||
type: 'folder',
|
type: 'folder',
|
||||||
discovered: true,
|
discovered: true,
|
||||||
children: updatedNodes,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
eventFiles.forEach((file) => {
|
||||||
|
newRoot.addChild(file, { makeParents: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
this.root = newRoot
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
handleEvent(event) {
|
||||||
|
|||||||
@@ -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'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
import File from './file.js'
|
import File from './file.js'
|
||||||
import { DuplicateItemError, ParentNotExistsError } from './errors.js'
|
import {
|
||||||
|
DuplicateItemError,
|
||||||
|
ParentNotExistsError,
|
||||||
|
FileNotExistsError,
|
||||||
|
} from './errors.js'
|
||||||
import { basename, dirname } from './utils.js'
|
import { basename, dirname } from './utils.js'
|
||||||
|
|
||||||
export default class FileNode extends File {
|
export default class FileNode extends File {
|
||||||
@@ -92,22 +96,4 @@ export default class FileNode extends File {
|
|||||||
.join('')
|
.join('')
|
||||||
return `${indent}${this.name}${suffix}\n${childrenString}`
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user