eltro/test/watch/builder.mjs

249 lines
5.4 KiB
JavaScript

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 })
.catch(() =>
this.delay(100)
.then(() => 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.rm(this.root, { recursive: true, force: true })
}
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)
}
Builder.prototype.delay = function(delay) {
return new Promise(res => {
setTimeout(res, delay)
})
}
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()
})
})
}
Counter.prototype.updateRes = function(res) {
this._res = res
}
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()
}