UNPKG

wzt-plugin-shifting

Version:

A simple CLI for publish your projects.

153 lines (137 loc) 4.77 kB
const path = require('path') const inquirer = require('inquirer') const date = require('phpdate-js') const SSH2Shell = require('ssh2shell') const chalk = require('chalk') const is = require('is') const isObject = is.object, isArray = is.array, isString = is.string, isEmpty = is.empty, isFn = is.fn, isUndefined = is.undefined const { error, warning, success } = require('./index.js').logger module.exports = function recover(module, env, next) { let { _history, recoverTemplate, ssh2shell, remotePath, ssh, shellTrashPath, preCommands, postCommands, _recover: { previous, length = 5 } } = module if (ssh.userName || ssh.user) { warning( "ssh配置中的'userName'与'user'请统一配置为'username',详情参考ssh2库(https://github.com/mscdex/ssh2)", 'recover', false, false ) } if (ssh.username) ssh.userName = ssh.username if (ssh.hostHash) ssh.hashMethod = ssh.hostHash if (ssh.passphrase) ssh.passPhrase = ssh.passphrase if (isEmpty(_history)) return warning('The history record is empty', 'recover', true) if (_history.length === 1) return warning( 'There is only one history record that dont need to recover', 'recover', true ) remotePath = path.posix.join(remotePath, '.') shellTrashPath = shellTrashPath ? path.posix.join(shellTrashPath, '.') : '/tmp/shiftingTrashDir' if (!/^(\/[^\/\s]+){2,}$/.test(remotePath)) return error( `Publish environment '${env}' option 'remotePath' file path is no vaild, the file path must be more than two level directory, and must be absolute path`, 'recover' ) if (shellTrashPath && !/^(\/[^\/\s]+){2,}$/.test(shellTrashPath)) return error( `Publish environment '${env}' option 'shellTrashPath' file path is no vaild, the file path must be more than two level directory, and must be absolute path`, 'recover' ) let p = previous ? Promise.resolve({ index: 1 }) : inquirer.prompt([ { type: 'list', name: 'index', message: 'Please select the version you want to recover', choices: _history.slice(1, +length + 1).map((v, k) => ({ name: recoverTemplate ? recoverTemplate(module, v, chalk) : `${chalk.gray(v.tag)} ${v._backupExt} ${v.gitMessage || ''}`, value: k + 1 })) } ]) p.then(({ index }) => { let record = _history[index] let { tag, _backupExt, localPathEntries } = record let _timeStamp = date('YmdHis') let commands = [ //保证远程环境垃圾箱必须存在 `mkdir -p ${shellTrashPath}`, //进入远程环境父目录 `cd ${localPathEntries ? remotePath : path.dirname(remotePath)}` ] let remotePathBackupPath = `${shellTrashPath + remotePath.replace(/\b\//g, '.')}.${_timeStamp}` if (localPathEntries) commands.push(`mkdir -p ${remotePathBackupPath}`) //根据发布文件(夹)数组生成的主要处理命令 let mainCommands = mainCmdFn( localPathEntries ? localPathEntries : [path.basename(remotePath)] ) if (!localPathEntries) { //进入remotePath的目录执行后命令 mainCommands.push(`cd ${remotePath}`) } function mainCmdFn(paths = []) { let result = [] paths.forEach(v => { let pathV = path.posix.join(v, '.') let backupPath = `${remotePathBackupPath}/${path.normalize(pathV)}` if (!/^(\/[^\/\s]+){2,}$/.test(backupPath)) { return error('Combine path error', 'recover') } result.push( `mv ${pathV} ${localPathEntries ? backupPath : remotePathBackupPath}` ) result.push(`mv ${pathV}.${_backupExt} ${pathV}`) }) return result } //合并命令 commands = [...commands, ...mainCommands] //增加前置处理命令 if (preCommands) commands = [...preCommands, ...commands] //增加后置置处理命令 if (postCommands) commands = [...commands, ...postCommands] _history.splice(index, 1) delete record._backupExt record._timeStamp = _timeStamp _history.splice(0, 1, record) let opt = Object.assign({ idleTimeOut: 10000 }, ssh2shell, { server: ssh, commands }) let SSH = new SSH2Shell(opt) SSH.on('data', data => { process.stdout.write(data) }) SSH.connect(text => { console.log('\n') setTimeout(() => { module._customHistory = true success(`recover success`) next(null) }, 500) }) }) }