mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
feat: add merge function
Able to deal with: 1. merge a subtree
This commit is contained in:
1 parent
1778780364
commit
a66de4dfe1
5 files changed
+114
-5
No files matched your search
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "File Graph Yarn Jest",
|
||||
"runtimeExecutable": "yarn",
|
||||
"args": ["test", "--runInBand"],
|
||||
"cwd": "${workspaceFolder}/packages/file-graph",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import { basename } from './utils'
|
||||
|
||||
export default class File {
|
||||
constructor({ path, name, type, discovered }) {
|
||||
constructor({ path, type, discovered }) {
|
||||
this.path = path
|
||||
this.name = name
|
||||
this.name = basename(path)
|
||||
this.type = type
|
||||
this.discovered = discovered
|
||||
}
|
||||
|
||||
@@ -11,11 +11,15 @@ export default class FileNode extends File {
|
||||
addChild(fileInput, { makeParents } = {}) {
|
||||
const file = new FileNode(fileInput)
|
||||
if (file.path === this.path) {
|
||||
throw new DuplicateItemError('File already exists in the tree')
|
||||
throw new DuplicateItemError(
|
||||
`File ${file.path} already exists in the tree: ${this.toString()}`
|
||||
)
|
||||
}
|
||||
|
||||
if (this.children.some((child) => child.path === file.path)) {
|
||||
throw new DuplicateItemError('File already exists in the tree')
|
||||
throw new DuplicateItemError(
|
||||
`File ${file.path} already exists in the tree: ${this.toString()}`
|
||||
)
|
||||
}
|
||||
|
||||
const parentPath = dirname(file.path)
|
||||
@@ -37,11 +41,47 @@ export default class FileNode extends File {
|
||||
})
|
||||
this.addChild(parent, { makeParents })
|
||||
} else {
|
||||
throw new ParentNotExistsError('Parent path not found in the tree')
|
||||
throw new ParentNotExistsError(
|
||||
`Parent path not found in the tree, ${file.path}, ${this.path}`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
merge(fileNode) {
|
||||
// Merge the children of the provided file node into this node
|
||||
// If a child already exists, merge the children of that child
|
||||
// If a child does not exist, add it to this node
|
||||
if (fileNode.path === this.path) {
|
||||
fileNode.children.forEach((child) => {
|
||||
const existingChild = this.children.find((c) => c.path === child.path)
|
||||
if (existingChild) {
|
||||
existingChild.merge(child)
|
||||
} else {
|
||||
this.children.push(child)
|
||||
}
|
||||
})
|
||||
|
||||
// If a child exists in this node but not in the provided node, remove it
|
||||
this.children = this.children.filter((child) =>
|
||||
fileNode.children.some((c) => c.path === child.path)
|
||||
)
|
||||
} else if (this.contains(fileNode)) {
|
||||
const childNode = this.children.find((child) => child.contains(fileNode))
|
||||
if (childNode) {
|
||||
childNode.merge(fileNode)
|
||||
} else {
|
||||
this.addChild(fileNode)
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
'Cannot merge file nodes with different paths',
|
||||
this.path,
|
||||
fileNode.path
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
const indent = ' '.repeat(this.path.split('/').length - 1)
|
||||
const suffix = this.isDirectory() ? '/' : ''
|
||||
|
||||
@@ -93,4 +93,53 @@ describe('FileNode', () => {
|
||||
currentNode = currentNode.children[0]
|
||||
}
|
||||
})
|
||||
|
||||
test('merge-two-trees', () => {
|
||||
const root = {
|
||||
path: '/',
|
||||
type: 'folder',
|
||||
}
|
||||
const files1 = [
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/d', type: 'file' },
|
||||
{ path: '/b/c/f', type: 'file' },
|
||||
]
|
||||
|
||||
const files2 = [
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/e', type: 'file' },
|
||||
{ path: '/b/c/g', type: 'file' },
|
||||
]
|
||||
|
||||
const expected = [
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/e', type: 'file' },
|
||||
{ path: '/b/c/g', type: 'file' },
|
||||
]
|
||||
|
||||
const node1 = new FileNode(root)
|
||||
files1.forEach((file) => node1.addChild(file))
|
||||
|
||||
const node2 = new FileNode(files2[0])
|
||||
files2.slice(1).forEach((file) => node2.addChild(file))
|
||||
|
||||
console.log('node1', node1.toString())
|
||||
console.log('node2', node2.toString())
|
||||
|
||||
const expectedNode = new FileNode(root)
|
||||
expected.forEach((file) => expectedNode.addChild(file))
|
||||
|
||||
console.log('expected', expectedNode.toString())
|
||||
|
||||
node1.merge(node2)
|
||||
|
||||
console.log('node1-after', node1.toString())
|
||||
|
||||
expect(node1.toString()).toBe(expectedNode.toString())
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,8 @@
|
||||
export function dirname(path) {
|
||||
const parts = path.split('/')
|
||||
if (parts.length <= 2) {
|
||||
return '/'
|
||||
}
|
||||
parts.pop()
|
||||
return parts.join('/')
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user