prt
Version:
Package Manager for Windows
158 lines (150 loc) • 4.29 kB
JavaScript
var url_parse = require('url').parse
var resolve = require('path').resolve
var extname = require('path').extname
var basename = require('path').basename
var dirname = require('path').dirname
var existsSync = require('fs').existsSync
//var unlinkSync = require('fs').unlinkSync
var writeFileSync = require('fs').writeFileSync
var createWriteStream = require('fs').createWriteStream
var os_arch = require('os').arch
var shell = require('shelljs')
var glob = require('glob')
var _7z = require('7zip')['7z']
var Download = require('download')
//var dwn = require('dwn')
//var bar = require('progress-bar').create(process.stdout)
//var mkdirpSync = require('mkdirp').sync
var action = process.argv[2]
switch (action) {
case 'install':
var name = process.argv[3]
var version = process.argv[4]
do_install(name, version, function(err){
if (err) {
console.error(err)
process.exit(1)
}
});
break; // dont forget `break`
default:
console.error('action not found')
process.exit(1)
}
function do_install(name, version, callback){
var listdir = resolve(__dirname, '../list/')
var modname = resolve(listdir, name)
if (modname.indexOf(listdir) !== 0) { // bad guy detected
callback(new Error('invalid pak'))
return
}
try {
var mod = require(modname)
} catch(err) {
console.error('pak not found')
callback(err)
return
}
if (!version) version = mod.version_list[0] // defaults latest
mod.name = name // append `name`
mod.version = version // append `version`
download(mod, function(err){
if (err) {
unpack_done(err)
return
}
if (mod.ext === '.exe' || mod.ext === '.msi') {
if (mod.entry_list) { // single exe
unpack(mod, unpack_done)
} else { // installer
shell.exec('prts "' + mod.file + '"', { silent: true })
console.log('installer spawn complete')
}
return
} else {
unpack(mod, unpack_done)
}
})
function unpack_done(err){
if (err) {
callback(err)
return
}
try {
link(mod)
} catch(err) {
console.error('link fail')
callback(err)
return
}
console.log('link complete')
callback(null)
}
}
function link(mod){
var entryfiles = mod.entry_list.reduce(function(arr, pattern){
var files = glob.sync(pattern, { cwd: mod.dest })
arr.push.apply(arr, files)
return arr
}, [])
entryfiles.forEach(function(file){
var ext = extname(file)
var base = basename(file, ext)
var cmdfile = resolve(process.env.windir, base + '.cmd')
var cmd = '"' + resolve(mod.dest, file) + '" %*'
writeFileSync(cmdfile, cmd)
console.log('link created', cmdfile) // exec (blocked)
// would be too noisy ;)
//var cmdfile_ = resolve(process.env.windir, name + '_.cmd')
//var cmd_ = 'prts "' + cmdfile + '" %*'
//writeFileSync(cmdfile_, cmd_)
//console.log('link created', cmdfile_) // spawn (detached)
})
}
function unpack(mod, callback){
// fixme: 7z -o not work
// fixme: cwd chdir hack
var _cwd = process.cwd()
process.chdir(mod.dest)
//if (!shell.which('7z')) {
// callback(new Error('install 7z first'))
// return
//}
// 7z -y
// http://superuser.com/questions/483037/extract-and-overwrite-existing-files
shell.exec('"' + _7z + '" x -y "' + mod.file + '"', { silent: true })
process.chdir(_cwd)
//unlinkSync(mod.file)
callback(null)
}
function download(mod, callback){
var uri = mod.get_url(mod.version, os_arch())
var dest = resolve(__dirname, '../cache', mod.name, mod.version)
var fname = basename(url_parse(uri).pathname)
var file = resolve(dest, fname)
var ext = extname(file)
mod.uri = uri // append `uri`
mod.dest = dest // append `dest`
mod.file = file // append `file`
mod.ext = ext // append `file`
if (existsSync(file) ) {
console.log('already exist', file)
callback(null)
return
}
console.log('downloading from', uri)
console.log('saving to', file)
new Download({ extract: false })
.get(uri)
.dest(dest)
.run(function(err){
if (err) {
console.error('download fail')
callback(err)
return
}
console.log('download complete')
callback(null)
})
}