Upgrade feature backend

This commit is contained in:
NGPixel 2017-02-13 23:30:42 -05:00
parent 391afc4d7a
commit 41d20db810
2 changed files with 98 additions and 4 deletions

View File

@ -1,10 +1,14 @@
'use strict' 'use strict'
const Promise = require('bluebird') const Promise = require('bluebird')
const https = require('follow-redirects').https const crypto = require('crypto')
const fs = Promise.promisifyAll(require('fs-extra')) const fs = Promise.promisifyAll(require('fs-extra'))
const https = require('follow-redirects').https
const klaw = require('klaw')
const path = require('path') const path = require('path')
const pm2 = Promise.promisifyAll(require('pm2'))
const tar = require('tar') const tar = require('tar')
const through2 = require('through2')
const zlib = require('zlib') const zlib = require('zlib')
const _ = require('lodash') const _ = require('lodash')
@ -13,30 +17,118 @@ module.exports = {
_remoteFile: 'https://github.com/Requarks/wiki/releases/download/{0}/wiki-js.tar.gz', _remoteFile: 'https://github.com/Requarks/wiki/releases/download/{0}/wiki-js.tar.gz',
_installDir: '', _installDir: '',
/**
* Install a version of Wiki.js
*
* @param {any} targetTag The version to install
* @returns {Promise} Promise of the operation
*/
install (targetTag) { install (targetTag) {
let self = this let self = this
self._installDir = path.resolve(ROOTPATH, appconfig.paths.data, 'install') self._installDir = path.resolve(ROOTPATH, appconfig.paths.data, 'install')
return fs.ensureDirAsync(self._installDir).then(() => { return fs.ensureDirAsync(self._installDir).then(() => {
return fs.emptyDirAsync(self._installDir)
}).then(() => {
let remoteURL = _.replace(self._remoteFile, '{0}', targetTag) let remoteURL = _.replace(self._remoteFile, '{0}', targetTag)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
/**
* Fetch tarball and extract to temporary folder
*/
https.get(remoteURL, resp => { https.get(remoteURL, resp => {
if (resp.statusCode !== 200) { if (resp.statusCode !== 200) {
return reject(new Error('Remote file not found')) return reject(new Error('Remote file not found'))
} }
winston.info('[SERVER.System] Install tarball found. Downloading...')
resp.pipe(zlib.createGunzip()) resp.pipe(zlib.createGunzip())
.pipe(tar.Extract({ path: self._installDir })) .pipe(tar.Extract({ path: self._installDir }))
.on('error', err => reject(err)) .on('error', err => reject(err))
.on('end', () => { .on('end', () => {
resolve(true) winston.info('[SERVER.System] Tarball extracted. Comparing files...')
/**
* Replace old files
*/
klaw(self._installDir)
.on('error', err => reject(err))
.on('end', () => {
winston.info('[SERVER.System] All files were updated successfully.')
resolve(true)
})
.pipe(self.replaceFile())
}) })
}) })
}).then(() => {
}) })
}).then(() => {
winston.info('[SERVER.System] Cleaning install leftovers...')
return fs.removeAsync(self._installDir).then(() => {
winston.info('[SERVER.System] Restarting Wiki.js...')
return pm2.restartAsync('wiki').catch(err => {
winston.error('Unable to restart Wiki.js via pm2... Do a manual restart!')
process.exit()
})
})
}).catch(err => {
winston.warn(err)
})
},
/**
* Replace file if different
*/
replaceFile () {
let self = this
return through2.obj((item, enc, next) => {
if (!item.stats.isDirectory()) {
self.digestFile(item.path).then(sourceHash => {
let destFilePath = _.replace(item.path, self._installDir, ROOTPATH)
return self.digestFile(destFilePath).then(targetHash => {
if (sourceHash === targetHash) {
winston.log('verbose', '[SERVER.System] Skipping ' + destFilePath)
return fs.removeAsync(item.path).then(() => {
return next() || true
})
} else {
winston.log('verbose', '[SERVER.System] Updating ' + destFilePath + '...')
return fs.moveAsync(item.path, destFilePath, { overwrite: true }).then(() => {
return next() || true
})
}
})
}).catch(err => {
throw err
})
} else {
next()
}
})
},
/**
* Generate the hash of a file
*
* @param {String} filePath The absolute path of the file
* @return {Promise<String>} Promise of the hash result
*/
digestFile: (filePath) => {
return new Promise((resolve, reject) => {
let hash = crypto.createHash('sha1')
hash.setEncoding('hex')
fs.createReadStream(filePath)
.on('error', err => { reject(err) })
.on('end', () => {
hash.end()
resolve(hash.read())
})
.pipe(hash)
}).catch(err => {
if (err.code === 'ENOENT') {
return '0'
} else {
throw err
}
}) })
} }
} }

View File

@ -82,6 +82,7 @@
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
"passport-windowslive": "^1.0.2", "passport-windowslive": "^1.0.2",
"passport.socketio": "^3.7.0", "passport.socketio": "^3.7.0",
"pm2": "^2.4.0",
"pug": "^2.0.0-beta11", "pug": "^2.0.0-beta11",
"read-chunk": "^2.0.0", "read-chunk": "^2.0.0",
"remove-markdown": "^0.1.0", "remove-markdown": "^0.1.0",
@ -96,6 +97,7 @@
"stopword": "^0.1.1", "stopword": "^0.1.1",
"stream-to-promise": "^2.2.0", "stream-to-promise": "^2.2.0",
"tar": "^2.2.1", "tar": "^2.2.1",
"through2": "^2.0.3",
"validator": "^6.2.0", "validator": "^6.2.0",
"validator-as-promised": "^1.0.2", "validator-as-promised": "^1.0.2",
"winston": "^2.3.0" "winston": "^2.3.0"