wzt-plugin-shifting
Version:
A simple CLI for publish your projects.
181 lines (171 loc) • 6.47 kB
JavaScript
const fs = require('fs')
const os = require('os')
const path = require('path')
const zlib = require('zlib')
const is = require('is')
const tar = require('tar-fs')
const createHash = require('crypto').createHash
const md5 = input => {
return createHash('md5')
.update(input)
.digest('hex')
}
const ora = require('ora')
const multimatch = require('multimatch')
const logger = require('./index.js').logger
module.exports = function compress(module, env, next) {
let isObject = is.object,
isArray = is.array,
isString = is.string,
isEmpty = is.empty,
isFn = is.fn,
isUndefined = is.undefined
let localLogger = (local, type) => (msg, end = false, cb = next) =>
logger[type](msg, local, end, cb)
let error = localLogger('compress', 'error')
let warning = localLogger('compress', 'warning')
if (module.diff && module.nohistory)
warning(
`File diff dependency on history, please dont set 'nohistory'`,
false,
() => {}
)
if (module.nohistory) module.diff = false
if (module.diff) module.merge = true
let {
localPath,
localPathEntries,
localPathMap,
localPathMapStream,
localPathIgnore,
buildCommand,
nobuild,
merge,
nohistory,
diff,
localTarFileDir,
tarFilename,
_latest = {},
_current = {}
} = module
if (isUndefined(localPath) && isUndefined(localPathEntries))
return error(
`Publish environment '${env}' option 'localPath' and 'localPathEntries' exist at least one. if you want to publish all files in the current directory, please set 'localPath' to '.'`
)
if (localPath && !isString(localPath))
return error(
`Publish environment '${env}' option 'localPath' must be a string`
)
if (
localPathEntries &&
!isString(localPathEntries) &&
!isArray(localPathEntries)
)
return error(
`Publish environment '${env}' option 'localPathEntries' must be a string or an array`
)
if (localTarFileDir && !isString(localTarFileDir))
return error(
`Publish environment '${env}' option 'localTarFileDir' must be a string`
)
if (tarFilename && !isString(tarFilename))
return error(
`Publish environment '${env}' option 'tarFilename' must be a string`
)
if (tarFilename && !/^\w+$/.test(tarFilename))
return error(
`Publish environment '${env}' option 'tarFilename' name is illegal, e.g. example.tar.gz only white example`
)
if (isString(localPathEntries)) localPathEntries = [localPathEntries]
if (localPathEntries && localPathEntries.some(path.isAbsolute))
return error(
`Publish environment '${env}' option 'localPathEntries' must all be relative paths, and all path must in the current working directory`
)
if (isString(localPathIgnore)) localPathIgnore = [localPathIgnore]
let _compressHash = md5(
[]
.concat(isFn(localPathIgnore) ? Math.random() : localPathIgnore || [])
.concat(localPath || 'localPath')
.concat(localPathEntries || 'localPathEntries')
.concat(localTarFileDir || 'localTarFileDir')
.concat(tarFilename || 'tarFilename')
.concat(diff ? Math.random() : 'diff')
.concat(nobuild ? 'nobuild' : buildCommand || 'buildCommand')
.join('')
).slice(0, 5)
module.localTarFileDir = localTarFileDir
? path.resolve(localTarFileDir)
: os.tmpdir()
module._compressHash = _compressHash
let hashPromiseName = `_${_compressHash}HashCompressPromise`
let p = this[hashPromiseName]
? this[hashPromiseName]
: (this[hashPromiseName] = new Promise((resolve, reject) => {
let option = {}
let curIndex = this._compressIndex || (this._compressIndex = 0)
let filename = `${
tarFilename ? tarFilename : 'fjcompress' + curIndex
}.tar.gz`
this._compressIndex++
if (this._metadata.check) return resolve({ filename })
let spinner = ora('Compressing...').start()
if (localPathEntries) option.entries = localPathEntries.slice()
let _latestFilesHash = _latest._filesHash
let _filesHash = merge ? Object.assign({}, _latestFilesHash) : {}
option.ignore = name => {
let isFile = fs.statSync(name).isFile()
let boolean = false
if (isFn(localPathIgnore)) boolean = localPathIgnore(name)
if (isArray(localPathIgnore) && !boolean)
boolean = !!multimatch([name], localPathIgnore, { dot: true })
.length
if (isFile && !boolean && !nohistory) {
let fileContentHash = md5(fs.readFileSync(name)).slice(0, 5)
if (
diff &&
_latestFilesHash &&
_latestFilesHash[name] &&
fileContentHash === _latestFilesHash[name]
)
boolean = true
_filesHash[name] = fileContentHash
}
return boolean
}
if (localPathMapStream) option.mapStream = localPathMapStream
option.map = localPathMap
? localPathMap
: header => {
header.mode = header.type === 'directory' ? 0755 : 0644 // change permission
return header
}
let pack = tar.pack(localPath || '.', option)
let gzStream = pack.pipe(zlib.createGzip())
gzStream.pipe(
fs.createWriteStream(path.join(module.localTarFileDir, filename))
)
// pack.pipe(zlib.createGzip()).pipe(fs.createWriteStream(path.join(module.localTarFileDir, filename)));
gzStream.on('error', err => {
spinner.fail('Compress failures')
resolve({ err })
})
gzStream.on('end', () => {
spinner.succeed('Compress success')
resolve({ filename, _filesHash, localPathEntries })
})
}))
p.then(({ filename, _filesHash, err = null }) => {
if (err) {
error(`Publish environment '${env}' compress failures`, false, () => {})
next(err)
} else {
module.tarFilename = filename
if (!nohistory && !this._metadata.check) {
if (localPathEntries) _current.localPathEntries = localPathEntries
_current._filesHash = _filesHash
}
logger.success(`env ${env} compress success`)
next(null, 'compress success')
}
})
}