2023-09-02 08:23:26 +00:00
|
|
|
import fs from 'fs/promises'
|
|
|
|
import fsSync from 'fs'
|
|
|
|
import path from 'path'
|
|
|
|
import { fileURLToPath } from 'url'
|
|
|
|
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
|
|
|
|
let structure = `
|
|
|
|
home/
|
|
|
|
a/
|
|
|
|
file1
|
|
|
|
file2
|
|
|
|
b/
|
|
|
|
file1
|
|
|
|
file2
|
|
|
|
c/
|
|
|
|
bb/
|
|
|
|
file1
|
|
|
|
file2
|
|
|
|
d/
|
|
|
|
file1
|
|
|
|
file2
|
|
|
|
e/
|
|
|
|
file1
|
|
|
|
file2
|
|
|
|
sub/
|
|
|
|
deep_node_modules/
|
|
|
|
ma/
|
|
|
|
file1
|
|
|
|
file2
|
|
|
|
mb/
|
|
|
|
file1
|
|
|
|
file2
|
|
|
|
mc/
|
|
|
|
`
|
|
|
|
|
|
|
|
let code = structure
|
|
|
|
.split('\n')
|
|
|
|
.filter(line => line)
|
|
|
|
.map(function(line) {
|
|
|
|
return {
|
|
|
|
indent: line.length - line.replace(/^\s+/,'').length,
|
|
|
|
type: /\/$/.test(line) ? 'dir': 'file',
|
|
|
|
text: line.replace(/^\s+|\s*\/\s*|\s+$/g, '')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
function join(arr) {
|
|
|
|
return arr.join('/')
|
|
|
|
}
|
|
|
|
|
|
|
|
function transform(arr) {
|
|
|
|
let result = []
|
|
|
|
let temp = []
|
|
|
|
let indent = 0
|
|
|
|
arr.forEach(function(line) {
|
|
|
|
if (!line.text) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
else if (!line.indent) {
|
|
|
|
temp.push(line.text)
|
|
|
|
result.push({type: line.type, text: join(temp) })
|
|
|
|
}
|
|
|
|
else if (indent < line.indent) {
|
|
|
|
temp.push(line.text)
|
|
|
|
result[result.length - 1].type = 'dir'
|
|
|
|
result.push({type: line.type, text: join(temp) })
|
|
|
|
}
|
|
|
|
else if (indent === line.indent) {
|
|
|
|
temp.pop()
|
|
|
|
temp.push(line.text)
|
|
|
|
result.push({type: line.type, text: join(temp) })
|
|
|
|
}
|
|
|
|
else if(indent > line.indent) {
|
|
|
|
temp.pop()
|
|
|
|
temp.pop()
|
|
|
|
temp.push(line.text)
|
|
|
|
result.push({type: line.type, text: join(temp) })
|
|
|
|
}
|
|
|
|
|
|
|
|
indent = line.indent
|
|
|
|
})
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
function gracefully(promise) {
|
|
|
|
return promise.catch(function(err) {
|
|
|
|
console.log(err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function emptyFile(target) {
|
|
|
|
let folder = target.slice(0, target.lastIndexOf('/'))
|
|
|
|
|
|
|
|
/*return fs.mkdir(folder, { recursive: true, force: true })
|
|
|
|
.then(() => fs.open(target, 'w').then(fd => fd.close()))*/
|
|
|
|
|
|
|
|
return fs.stat(folder)
|
|
|
|
.catch(() => fs.mkdir(folder, { recursive: true, force: true }))
|
|
|
|
.then(() => {
|
|
|
|
return fs.open(target, 'w').then(fd => fd.close())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Builder() {
|
|
|
|
this.root = path.join(__dirname, '__TREE__')
|
|
|
|
this.transformed = transform(code)
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.init = async function() {
|
|
|
|
await Promise.all(
|
|
|
|
this.transformed.filter(line => line.type === 'dir').map(line => {
|
|
|
|
let target = path.join(this.root, line.text)
|
|
|
|
return gracefully(fs.mkdir(target, { recursive: true }))
|
|
|
|
})
|
|
|
|
)
|
|
|
|
await Promise.all(
|
|
|
|
this.transformed.filter(line => line.type !== 'dir').map(line => {
|
|
|
|
let target = path.join(this.root, line.text)
|
|
|
|
return gracefully(emptyFile(target))
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.getPath = function(fpath, sub) {
|
|
|
|
return path.join(this.root, fpath, sub || '')
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.modify = function(fpath, delay) {
|
|
|
|
if (delay) throw new Error('remove delay')
|
|
|
|
let filePath = this.getPath(fpath)
|
|
|
|
return fs.appendFile(filePath, 'hello')
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.remove = function(fpath) {
|
|
|
|
let filePath = this.getPath(fpath)
|
|
|
|
return fs.rm(filePath, { recursive: true, force: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.removeSync = function(fpath) {
|
|
|
|
let filePath = this.getPath(fpath)
|
|
|
|
return fsSync.rmSync(filePath, { recursive: true, force: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.newFile = function(fpath, delay) {
|
|
|
|
if (delay) throw new Error('remove delay')
|
|
|
|
let filePath = this.getPath(fpath)
|
|
|
|
return emptyFile(filePath)
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.createDirectory = function(fpath) {
|
|
|
|
let filePath = this.getPath(fpath)
|
|
|
|
return fs.mkdir(filePath, { recursive: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.randomName = function() {
|
|
|
|
return Math.random().toString(36).substring(2, 14)
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.newRandomFiles = function(fpath, count) {
|
|
|
|
return Promise.all(
|
|
|
|
new Array(count).fill(0).map(() => {
|
|
|
|
let name = this.randomName()
|
|
|
|
let filePath = this.getPath(fpath, name)
|
|
|
|
|
|
|
|
return emptyFile(filePath).then(() => name)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.cleanup = function() {
|
|
|
|
return fs.rmdir(this.root)
|
|
|
|
}
|
|
|
|
|
|
|
|
Builder.prototype.getAllDirectories = function() {
|
|
|
|
function walk(dir) {
|
|
|
|
let ret = []
|
|
|
|
fsSync.readdirSync(dir).forEach(function(d) {
|
|
|
|
let fpath = path.join(dir, d)
|
|
|
|
if (fsSync.statSync(fpath).isDirectory()) {
|
|
|
|
ret.push(fpath)
|
|
|
|
ret = ret.concat(walk(fpath))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
return walk(this.root)
|
|
|
|
}
|
|
|
|
|
2023-09-03 00:12:49 +00:00
|
|
|
Builder.prototype.delay = function(delay) {
|
|
|
|
return new Promise(res => {
|
|
|
|
setTimeout(res, delay)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
export function Counter(res, countTotal, waitForSignal = false) {
|
|
|
|
this._res = res
|
|
|
|
this.counter = 0
|
|
|
|
this._countTotal = countTotal
|
|
|
|
this._startCount = !waitForSignal
|
|
|
|
this._gotSignal = false
|
|
|
|
this._signal = null
|
|
|
|
}
|
|
|
|
|
|
|
|
Counter.prototype.waitForCount = function(promise) {
|
|
|
|
if (!promise) {
|
|
|
|
promise = Promise.resolve()
|
|
|
|
}
|
|
|
|
return new Promise(res => {
|
|
|
|
promise.then(() => {
|
|
|
|
this._signal = res
|
|
|
|
this.hasSignal()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-09-03 00:12:49 +00:00
|
|
|
Counter.prototype.updateRes = function(res) {
|
|
|
|
this._res = res
|
|
|
|
}
|
|
|
|
|
2023-09-02 08:23:26 +00:00
|
|
|
Counter.prototype.hasSignal = function() {
|
|
|
|
if (this._gotSignal && this._signal) {
|
|
|
|
this._gotSignal = false
|
|
|
|
let temp = this._signal
|
|
|
|
this._signal = null
|
|
|
|
temp()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Counter.prototype.startCounting = function() {
|
|
|
|
this._startCount = true
|
|
|
|
}
|
|
|
|
|
|
|
|
Counter.prototype.count = function() {
|
|
|
|
if (!this._startCount) return
|
|
|
|
|
|
|
|
this._gotSignal = true
|
|
|
|
this.counter++
|
|
|
|
if (this.counter === this._countTotal && this._res) {
|
|
|
|
this._res()
|
|
|
|
}
|
|
|
|
|
|
|
|
this.hasSignal()
|
|
|
|
}
|