Skip to content

Instantly share code, notes, and snippets.

@erwinv
Last active February 9, 2019 05:25
Show Gist options
  • Save erwinv/e50b0be64c070f9407c1a7f70183002f to your computer and use it in GitHub Desktop.
Save erwinv/e50b0be64c070f9407c1a7f70183002f to your computer and use it in GitHub Desktop.
backup paths exercise (FRP version)
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const readline = require('readline')
const R = require('ramda')
const Bacon = require('baconjs')
const Promise = require('bluebird')
const readdirAsync = Promise.promisify(fs.readdir)
const statAsync = Promise.promisify(fs.stat)
function readFirstLineAsync(filepath) {
return new Promise((resolve, reject) => {
const readStream = fs.createReadStream(filepath, 'utf8')
readStream.on('error', reject)
const rl = readline.createInterface({input: readStream})
rl.on('error', reject)
rl.on('line', line => {
readStream.close()
resolve(line)
})
})
}
function getBackupPathsRx(dir, parentpolicy='branch') {
return Bacon.fromPromise(Promise.resolve(
parentpolicy == 'branch' ? readFirstLineAsync(path.join(dir, '.backuppolicy')) : 'leaf'))
.mapError('leaf')
.map(R.pipe(
val => val.trim(),
policy => ['leaf', 'branch', 'ignore'].includes(policy) ? policy : 'leaf'
))
.flatMap(policy =>
Bacon.fromPromise(Promise.resolve(
policy == 'ignore' ? [] : readdirAsync(dir)))
.flatMap(basenames => {
const fullpaths = basenames
.map(R.pipe(
base => ({dir, base}),
path.format,
path.normalize
))
return Bacon.fromArray(fullpaths)
})
.flatMap(fullpath => {
const withStatsP = statAsync(fullpath)
.then(stats => ({fullpath, stats}))
return Bacon.fromPromise(withStatsP)
})
.flatMap(({fullpath, stats}) =>
stats.isFile() ? Bacon.once(fullpath) :
stats.isDirectory() ? getBackupPathsRx(fullpath, policy) :
Bacon.never()
)
)
}
const runningAsMain = require.main == module && !module.parent
if (runningAsMain) {
if (process.argv.length < 3)
return console.error('no dirpath given')
const [,, dir] = process.argv
getBackupPathsRx(dir)
.onValue(console.log)
} else {
Object.assign(module.exports, {
getBackupPathsRx
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment