UNPKG

fis-repo-client

Version:

fis-repo-client

637 lines (587 loc) 17.2 kB
var fs = require('fs'), pth = require('path'), request = require('request'), _exists = fs.existsSync || pth.existsSync, toString = Object.prototype.toString, log = require("./log.js"), iconv; var IS_WIN = process.platform.indexOf('win') === 0; var TEXT_FILE_EXTS = [ 'css', 'tpl', 'js', 'php', 'txt', 'json', 'xml', 'htm', 'text', 'xhtml', 'html', 'md', 'conf', 'po', 'config', 'tmpl', 'coffee', 'less', 'sass', 'jsp', 'scss', 'manifest', 'bak', 'asp', 'tmp', 'haml', 'jade' ], IMAGE_FILE_EXTS = [ 'svg', 'tif', 'tiff', 'wbmp', 'png', 'bmp', 'fax', 'gif', 'ico', 'jfif', 'jpe', 'jpeg', 'jpg', 'woff', 'cur' ]; function getIconv(){ if(!iconv){ iconv = require('iconv-lite'); } return iconv; } var _ = module.exports = function(){}; _.is = function(source, type){ return toString.call(source) === '[object ' + type + ']'; }; _.map = function(obj, callback, merge){ var index = 0; for(var key in obj){ if(obj.hasOwnProperty(key)){ if(merge){ callback[key] = obj[key]; } else if(callback(key, obj[key], index++)) { break; } } } }; _.pad = function(str, len, fill, pre){ if(str.length < len){ fill = (new Array(len)).join(fill || ' '); if(pre){ str = (fill + str).substr(-len); } else { str = (str + fill).substring(0, len); } } return str; }; _.merge = function(source, target){ if(_.is(source, 'Object') && _.is(target, 'Object')){ _.map(target, function(key, value){ source[key] = _.merge(source[key], value); }); } else { source = target; } return source; }; _.clone = function(source) { var ret; switch(toString.call(source)){ case '[object Object]': ret = {}; _.map(source, function(k, v){ ret[k] = _.clone(v); }); break; case '[object Array]': ret = []; source.forEach(function(ele){ ret.push(_.clone(ele)); }); break; default : ret = source; } return ret; }; _.escapeReg = function(str){ return str.replace(/[\.\\\+\*\?\[\^\]\$\(\){}=!<>\|:\/]/g, '\\$&'); }; _.escapeShellCmd = function(str){ return str.replace(/ /g, '"$&"'); }; _.escapeShellArg = function(cmd){ return '"' + cmd + '"'; }; _.stringQuote = function(str, quotes, trim){ var info = { origin : str, rest : str, quote : '' }; if(trim !== false) { str = str.trim(); } if(str){ quotes = quotes || '\'"'; var strLen = str.length - 1; for(var i = 0, len = quotes.length; i < len; i++){ var c = quotes[i]; if(str[0] === c && str[strLen] === c){ info.quote = c; info.rest = str.substring(1, strLen); break; } } } return info; }; _.exists = _exists; _.fs = fs; _.realpath = function(path){ if(path && _exists(path)){ path = fs.realpathSync(path); if(IS_WIN){ path = path.replace(/\\/g, '/'); } if(path !== '/'){ path = path.replace(/\/$/, ''); } return path; } else { return false; } }; _.realpathSafe = function(path){ return _.realpath(path) || _(path); }; _.isAbsolute = function(path) { if (IS_WIN) { return /^[a-z]:/i.test(path); } else { if(path === '/'){ return true; } else { var split = path.split('/'); if(split[0] === '~'){ return true; } else if(split[0] === '' && split[1]) { return _.isDir('/' + split[1] + '/' + split[2]); } else { return false; } } } }; _.isFile = function(path){ return _exists(path) && fs.statSync(path).isFile(); }; _.isDir = function(path){ return _exists(path) && fs.statSync(path).isDirectory(); }; _.mtime = function(path){ var time = 0; if(_exists(path)){ time = fs.statSync(path).mtime; } return time; }; _.touch = function(path, mtime){ if(!_exists(path)){ _.write(path, ''); } if(mtime instanceof Date){ //do nothing for quickly determining. } else if(typeof mtime === 'number') { var time = new Date(); time.setTime(mtime); mtime = time; } else { log.error('invalid argument [mtime]'); } fs.utimesSync(path, mtime, mtime); }; _.isWin = function(){ return IS_WIN; }; function getFileTypeReg(type){ var map = []; if(type === 'text'){ map = TEXT_FILE_EXTS; } else if(type === 'image'){ map = IMAGE_FILE_EXTS; } else { log.error('invalid file type [' + type + ']'); } map = map.join('|'); return new RegExp('\\.(?:' + map + ')$', 'i'); } _.isTextFile = function(path){ return getFileTypeReg('text').test(path || ''); }; _.isImageFile = function(path){ return getFileTypeReg('image').test(path || ''); }; _.mkdir = function(path, mode){ if (typeof mode === 'undefined') { //511 === 0777 mode = 511 & (~process.umask()); } if(_exists(path)) return; path.split('/').reduce(function(prev, next) { if(prev && !_exists(prev)) { fs.mkdirSync(prev, mode); } return prev + '/' + next; }); if(!_exists(path)) { fs.mkdirSync(path, mode); } }; _.toEncoding = function(str, encoding){ return getIconv().toEncoding(String(str), encoding); }; _.isUtf8 = function(bytes) { var i = 0; while(i < bytes.length) { if((// ASCII bytes[i] == 0x09 || bytes[i] == 0x0A || bytes[i] == 0x0D || (0x20 <= bytes[i] && bytes[i] <= 0x7E) )) { i += 1; continue; } if((// non-overlong 2-byte (0xC2 <= bytes[i] && bytes[i] <= 0xDF) && (0x80 <= bytes[i+1] && bytes[i+1] <= 0xBF) )) { i += 2; continue; } if( (// excluding overlongs bytes[i] == 0xE0 && (0xA0 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) && (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) ) || (// straight 3-byte ((0xE1 <= bytes[i] && bytes[i] <= 0xEC) || bytes[i] == 0xEE || bytes[i] == 0xEF) && (0x80 <= bytes[i + 1] && bytes[i+1] <= 0xBF) && (0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF) ) || (// excluding surrogates bytes[i] == 0xED && (0x80 <= bytes[i+1] && bytes[i+1] <= 0x9F) && (0x80 <= bytes[i+2] && bytes[i+2] <= 0xBF) ) ) { i += 3; continue; } if( (// planes 1-3 bytes[i] == 0xF0 && (0x90 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) && (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) && (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF) ) || (// planes 4-15 (0xF1 <= bytes[i] && bytes[i] <= 0xF3) && (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) && (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) && (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF) ) || (// plane 16 bytes[i] == 0xF4 && (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x8F) && (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) && (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF) ) ) { i += 4; continue; } return false; } return true; }; _.readBuffer = function(buffer){ if(_.isUtf8(buffer)){ buffer = buffer.toString('utf8'); if (buffer.charCodeAt(0) === 0xFEFF) { buffer = buffer.substring(1); } } else { buffer = getIconv().decode(buffer, 'gbk'); } return buffer; }; _.read = function(path, convert){ var content = false; if(_exists(path)){ content = fs.readFileSync(path); if(convert || _.isTextFile(path)){ content = _.readBuffer(content); } } else { log.error('unable to read file[' + path + ']: No such file or directory.'); } return content; }; _.write = function(path, data, charset, append){ if(!_exists(path)){ _.mkdir(_.pathinfo(path).dirname); } if(charset){ data = getIconv().encode(data, charset); } if(append) { fs.appendFileSync(path, data, null); } else { fs.writeFileSync(path, data, null); } }; _.filter = function(str, include, exclude){ if(typeof include === 'string'){ include = _.glob(include); } if(typeof exclude === 'string'){ exclude = _.glob(exclude); } return !((!!include && str.search(include) < 0) || (!!exclude && str.search(exclude) > -1)); }; _.glob = function(pattern, str){ var sep = _.escapeReg('/'); pattern = new RegExp('^' + sep + '?' + _.escapeReg( pattern .replace(/\\/g, '/') .replace(/^\//, '') ) .replace(new RegExp(sep + '\\*\\*' + sep, 'g'), sep + '.*(?:' + sep + ')?') .replace(new RegExp(sep + '\\*\\*', 'g'), sep + '.*') .replace(/\\\*\\\*/g, '.*') .replace(/\\\*/g, '[^' + sep + ']*') .replace(/\\\?/g, '[^' + sep + ']') + '$', 'i' ); if(typeof str === 'string'){ return pattern.test(str); } else { return pattern; } }; _.find = function(rPath, include, exclude){ var list = [], path = _.realpath(rPath); if(path){ var stat = fs.statSync(path); if(stat.isDirectory()){ fs.readdirSync(path).forEach(function(p){ if(p[0] != '.') { list = list.concat(_.find(path + '/' + p, include, exclude)); } }); } else if(stat.isFile() && _.filter(path, include, exclude)) { list.push(path); } } else { log.error('unable to find [' + rPath + ']: No such file or No such file or directory.'); } return list.sort(); }; _.del = function(rPath, include, exclude){ var removedAll = true, path = _.realpath(rPath); if(path) { if(/^(?:\w:)?\/$/.test(path)){ log.error('unable to delete directory [' + rPath + '].'); } var stat = fs.statSync(path); if(stat.isDirectory()){ fs.readdirSync(path).forEach(function(name){ if(name != '.' && name != '..') { removedAll = _.del(path + '/' + name, include, exclude) && removedAll; } }); if(removedAll) { fs.rmdirSync(path); } } else if(stat.isFile() && _.filter(path, include, exclude)) { fs.unlinkSync(path); } else { removedAll = false; } } else { //this.log.error('unable to delete [' + rPath + ']: No such file or No such file or directory.'); } return removedAll; }; _.copy = function(rSource, target, include, exclude, uncover, move){ var removedAll = true, source = _.realpath(rSource); target = _(target); if(source){ var stat = fs.statSync(source); if(stat.isDirectory()){ fs.readdirSync(source).forEach(function(name){ if(name != '.' && name != '..') { removedAll = _.copy( source + '/' + name, target + '/' + name, include, exclude, uncover, move ) && removedAll; } }); if(move && removedAll) { fs.rmdirSync(source); } } else if(stat.isFile() && _.filter(source, include, exclude)){ if(uncover && _exists(target)){ //uncover removedAll = false; } else { _.write(target, fs.readFileSync(source, null)); if(move) { fs.unlinkSync(source); } } } else { removedAll = false; } } else { log.error('unable to copy [' + rSource + ']: No such file or No such file or directory.'); } return removedAll; }; _.ext = function(str){ var info = _.query(str), pos; str = info.fullname = info.rest; if((pos = str.lastIndexOf('/')) > -1){ if(pos === 0){ info.rest = info.dirname = '/'; } else { info.dirname = str.substring(0, pos); info.rest = info.dirname + '/'; } str = str.substring(pos + 1); } else { info.rest = info.dirname = ''; } if((pos = str.lastIndexOf('.')) > -1){ info.ext = str.substring(pos).toLowerCase(); info.filename = str.substring(0, pos); info.basename = info.filename + info.ext; } else { info.basename = info.filename = str; info.ext = ''; } info.rest += info.filename; return info; }; _.query = function(str){ var rest = str, pos = rest.indexOf('?'), query = ''; if(pos > -1){ query = rest.substring(pos); rest = rest.substring(0, pos); } rest = rest.replace(/\\/g, '/'); if(rest !== '/'){ rest = rest.replace(/\/\.?$/, ''); } return { origin : str, rest : rest, query : query }; }; _.pathinfo = function(path){ //can not use _() method directly for the case _.pathinfo('a/'). var type = typeof path; if(arguments.length > 1) { path = Array.prototype.join.call(arguments, '/'); } else if(type === 'string') { //do nothing for quickly determining. } else if(type === 'object') { path = Array.prototype.join.call(path, '/'); } return _.ext(path); }; _.readJSON = function(path){ var json = _.read(path), result = {}; try { result = JSON.parse(json); } catch(e){ log.error('parse json file[' + path + '] fail, error [' + e.message + ']'); } return result; }; /** * * @param {String} type log的类型:error和log * @param {String} message log的内容 * @param {String} color log的颜色:black、red、green、yellow、blue、purple、white * @param {Boolean} exit 是否终止程序 */ //todo : log方法重构,参照jam中的颜色处理方案 _.log = function(type, message, color, exit){ color = color.toLowerCase(); switch(color){ case "black": color = 30; break; case "red": color = 31; break; case "green": color = 32; break; case "yellow": color = 33; break; case "blue": color = 34; break; case "purple": color = 35; break; case "white": color = 37; break; default : color = 37; break; } var templateStr = "\033[" + color + "m%s\033[m "; if(type == "error"){ console.error(templateStr, message); }else{ console.log(templateStr, message); } if(exit){ process.exit(1); } }; /** * 检查文件是否为zip格式。 * 检查zip文件的头标识 0x04034b50 和结束标识 0x06054b50 * @param file * @returns {boolean} */ _.isZip = function(file){ var ENDSIG = 0x06054b50; var LOCSIG = 0x04034b50; var COMMENT_LENGTH = 0xFFFF; var END_HEADER_SIZE = 22; var inBuffer = fs.readFileSync(file); var i = inBuffer.length - END_HEADER_SIZE, // END header size n = Math.max(0, i - COMMENT_LENGTH), // 0xFFFF is the max zip file comment length endOffset = 0; // Start offset of the END header for(i; i >= n; i--){ if (inBuffer[i] != 0x50) continue; // quick check that the byte is 'P' if (inBuffer.readUInt32LE(i) == ENDSIG) { // "PK\005\006" endOffset = i; break; } } if(endOffset && inBuffer.readUInt32LE(0) == LOCSIG){ return true; } return false; }; _.in_array = function(stringToSearch, arrayToSearch){ for (s = 0; s < arrayToSearch.length; s++) { thisEntry = arrayToSearch[s].toString(); if (thisEntry == stringToSearch) { return true; } } return false; }; _.sprintf = function () { return require('util').format.apply(this, arguments); }