From 2c1da3458a931788dad375c3acd0d5d755dac538 Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Mon, 9 Dec 2019 16:30:17 +0100 Subject: [PATCH] chore(backups-cli): move utils in their own module --- @xen-orchestra/backups-cli/_asyncMap.js | 7 +++ @xen-orchestra/backups-cli/_fs.js | 27 ++++++++++ .../backups-cli/commands/clean-vms.js | 52 ++++++------------- 3 files changed, 49 insertions(+), 37 deletions(-) create mode 100644 @xen-orchestra/backups-cli/_asyncMap.js create mode 100644 @xen-orchestra/backups-cli/_fs.js diff --git a/@xen-orchestra/backups-cli/_asyncMap.js b/@xen-orchestra/backups-cli/_asyncMap.js new file mode 100644 index 000000000..faada29ec --- /dev/null +++ b/@xen-orchestra/backups-cli/_asyncMap.js @@ -0,0 +1,7 @@ +const curryRight = require('lodash/curryRight') + +module.exports = curryRight((iterable, fn) => + Promise.all( + Array.isArray(iterable) ? iterable.map(fn) : Array.from(iterable, fn) + ) +) diff --git a/@xen-orchestra/backups-cli/_fs.js b/@xen-orchestra/backups-cli/_fs.js new file mode 100644 index 000000000..779feb2fa --- /dev/null +++ b/@xen-orchestra/backups-cli/_fs.js @@ -0,0 +1,27 @@ +const fs = require('promise-toolbox/promisifyAll')(require('fs')) +module.exports = fs + +// - easier: +// - single param for direct use in `Array#map` +// - files are prefixed with directory path +// - safer: returns empty array if path is missing or not a directory +fs.readdir2 = path => + fs.readdir(path).then( + entries => { + entries.forEach((entry, i) => { + entries[i] = `${path}/${entry}` + }) + + return entries + }, + error => { + if ( + error != null && + (error.code === 'ENOENT' || error.code === 'ENOTDIR') + ) { + console.warn('WARN: readdir(%s)', path, error) + return [] + } + throw error + } + ) diff --git a/@xen-orchestra/backups-cli/commands/clean-vms.js b/@xen-orchestra/backups-cli/commands/clean-vms.js index 9391f1022..b511a653a 100644 --- a/@xen-orchestra/backups-cli/commands/clean-vms.js +++ b/@xen-orchestra/backups-cli/commands/clean-vms.js @@ -6,27 +6,21 @@ let force // ----------------------------------------------------------------------------- const assert = require('assert') +const flatten = require('lodash/flatten') const getopts = require('getopts') const lockfile = require('proper-lockfile') +const pipe = require('promise-toolbox/pipe') const { default: Vhd } = require('vhd-lib') -const { curryRight, flatten } = require('lodash') const { dirname, resolve } = require('path') const { DISK_TYPE_DIFFERENCING } = require('vhd-lib/dist/_constants') -const { pipe, promisifyAll } = require('promise-toolbox') -const fs = promisifyAll(require('fs')) +const asyncMap = require('../_asyncMap') +const fs = require('../_fs') + const handler = require('@xen-orchestra/fs').getHandler({ url: 'file://' }) // ----------------------------------------------------------------------------- -const asyncMap = curryRight((iterable, fn) => - Promise.all( - Array.isArray(iterable) ? iterable.map(fn) : Array.from(iterable, fn) - ) -) - -const filter = (...args) => thisArg => thisArg.filter(...args) - const isGzipFile = async fd => { // https://tools.ietf.org/html/rfc1952.html#page-5 const magicNumber = Buffer.allocUnsafe(2) @@ -89,24 +83,6 @@ const isValidXva = async path => { const noop = Function.prototype -const readDir = path => - fs.readdir(path).then( - entries => { - entries.forEach((entry, i) => { - entries[i] = `${path}/${entry}` - }) - - return entries - }, - error => { - // a missing dir is by definition empty - if (error != null && error.code === 'ENOENT') { - return [] - } - throw error - } - ) - // ----------------------------------------------------------------------------- // chain is an array of VHDs from child to parent @@ -157,12 +133,12 @@ async function mergeVhdChain(chain) { const listVhds = pipe([ vmDir => vmDir + '/vdis', - readDir, - asyncMap(readDir), + fs.readdir2, + asyncMap(fs.readdir2), flatten, - asyncMap(readDir), + asyncMap(fs.readdir2), flatten, - filter(_ => _.endsWith('.vhd')), + _ => _.filter(_ => _.endsWith('.vhd')), ]) async function handleVm(vmDir) { @@ -239,10 +215,12 @@ async function handleVm(vmDir) { await Promise.all(deletions) } - const [jsons, xvas] = await readDir(vmDir).then(entries => [ - entries.filter(_ => _.endsWith('.json')), - new Set(entries.filter(_ => _.endsWith('.xva'))), - ]) + const [jsons, xvas] = await fs + .readdir2(vmDir) + .then(entries => [ + entries.filter(_ => _.endsWith('.json')), + new Set(entries.filter(_ => _.endsWith('.xva'))), + ]) await asyncMap(xvas, async path => { // check is not good enough to delete the file, the best we can do is report