2015-10-02 17:33:10 +03:00
|
|
|
/**********************************************************************
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
**********************************************************************/
|
2016-08-20 22:49:36 +03:00
|
|
|
(typeof(define)[0]=='u'?function(f){module.exports=f(require)}:define)(
|
|
|
|
|
function(require){ var module={} // makes module AMD/node compatible...
|
|
|
|
|
/*********************************************************************/
|
2015-10-02 17:33:10 +03:00
|
|
|
|
2016-05-28 16:29:57 +03:00
|
|
|
if(typeof(process) != 'undefined'){
|
|
|
|
|
var os = requirejs('os')
|
|
|
|
|
var fs = requirejs('fs')
|
|
|
|
|
var path = requirejs('path')
|
|
|
|
|
var glob = requirejs('glob')
|
|
|
|
|
var guaranteeEvents = requirejs('guarantee-events')
|
|
|
|
|
|
|
|
|
|
} else {
|
2016-04-15 02:10:36 +03:00
|
|
|
return module
|
2016-01-08 07:30:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-10-02 17:33:10 +03:00
|
|
|
//var DEBUG = DEBUG != null ? DEBUG : true
|
|
|
|
|
|
2015-12-08 07:42:07 +03:00
|
|
|
var object = require('../object')
|
2015-10-02 17:33:10 +03:00
|
|
|
var browse = require('./browse')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
|
// XXX need a root management to do OS-specific root dir management...
|
|
|
|
|
// e.g. X:/.. and /Volume/..
|
|
|
|
|
|
2015-10-02 17:37:18 +03:00
|
|
|
// XXX mostly works, does not list drive letter root dirs, deeper paths
|
|
|
|
|
// work...
|
2015-10-13 02:41:47 +03:00
|
|
|
// XXX appears to hang and crash on large lists....
|
2015-10-02 17:33:10 +03:00
|
|
|
var listDirGlob =
|
|
|
|
|
module.listDirGlob =
|
|
|
|
|
function(path, make){
|
2016-04-25 14:02:52 +03:00
|
|
|
var that = this
|
2015-10-02 17:33:10 +03:00
|
|
|
path = path.constructor == Array ? path.join('/') : path
|
|
|
|
|
path = /^[a-zA-Z]:/.test(path.trim()) ? path : '/'+path
|
|
|
|
|
|
|
|
|
|
// if not a glob then just list contents...
|
|
|
|
|
var fullpath = path.indexOf('*') >= 0
|
|
|
|
|
path = path.indexOf('*') < 0 ? path + '/*' : path
|
|
|
|
|
|
2016-04-15 02:09:02 +03:00
|
|
|
return new Promise(function(resolve, reject){
|
2016-04-25 14:02:52 +03:00
|
|
|
|
|
|
|
|
// XXX test...
|
|
|
|
|
if(that.options.dotDirs){
|
|
|
|
|
make(fullpath ? path + './' : './')
|
|
|
|
|
make(fullpath ? path + '../' : '../')
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-13 02:41:47 +03:00
|
|
|
// XXX do we need this???
|
|
|
|
|
/*guaranteeEvents([
|
|
|
|
|
'match',
|
|
|
|
|
'error',
|
|
|
|
|
],
|
|
|
|
|
glob.glob(path))*/
|
|
|
|
|
glob.glob(path)
|
|
|
|
|
.on('match', function(path){
|
|
|
|
|
fs.stat(path, function(err, stat){
|
|
|
|
|
if(err){
|
|
|
|
|
make(fullpath ? path : path.split(/[\\\/]/).pop(), null, true)
|
|
|
|
|
} else {
|
|
|
|
|
make(fullpath ? path : path.split(/[\\\/]/).pop()
|
|
|
|
|
+ (stat.isDirectory() ? '/' : ''))
|
|
|
|
|
}
|
|
|
|
|
})
|
2015-10-02 17:33:10 +03:00
|
|
|
})
|
2015-10-13 02:41:47 +03:00
|
|
|
// XXX do this after all the stats are done...
|
|
|
|
|
.on('end', function(){
|
|
|
|
|
resolve()
|
|
|
|
|
})
|
|
|
|
|
})
|
2015-10-02 17:33:10 +03:00
|
|
|
}
|
|
|
|
|
|
2015-10-12 02:29:08 +03:00
|
|
|
// XXX might be good to add some caching...
|
2015-10-02 17:33:10 +03:00
|
|
|
var listDirfs =
|
|
|
|
|
module.listDirfs =
|
|
|
|
|
function(path, make){
|
2015-12-10 06:56:52 +03:00
|
|
|
var that = this
|
2015-10-02 17:33:10 +03:00
|
|
|
path = path.constructor == Array ? path.join('/') : path
|
|
|
|
|
path = /^[a-zA-Z]:/.test(path.trim()) ? path : '/'+path
|
2015-10-09 17:14:41 +03:00
|
|
|
// XXX the windows root path must have a trailing '/'
|
|
|
|
|
path = /^[a-zA-Z]:$/.test(path.trim()) ? path+'/' : path
|
|
|
|
|
|
2015-10-12 02:29:08 +03:00
|
|
|
// XXX expose these as config...
|
2015-10-02 17:33:10 +03:00
|
|
|
var fullpath = false
|
2015-10-12 02:29:08 +03:00
|
|
|
|
2016-05-09 18:30:16 +03:00
|
|
|
// sync version of stat...
|
2016-05-09 19:04:02 +03:00
|
|
|
// XXX if we decide to keep this, then we'll need to cleanup the
|
|
|
|
|
// code below...
|
2016-05-09 18:30:16 +03:00
|
|
|
var stat = function(path){
|
|
|
|
|
return new Promise(function(resolve, reject){
|
|
|
|
|
try {
|
|
|
|
|
resolve(fs.statSync(path))
|
|
|
|
|
} catch(err){
|
|
|
|
|
reject(err)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2016-04-15 02:09:02 +03:00
|
|
|
var stat = function(path){
|
|
|
|
|
return new Promise(function(resolve, reject){
|
|
|
|
|
fs.stat.call(fs, path, function(err, res){
|
|
|
|
|
err ? reject(err) : resolve(res)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
2016-05-09 18:30:16 +03:00
|
|
|
*/
|
2015-10-12 02:43:22 +03:00
|
|
|
|
2015-10-12 02:29:08 +03:00
|
|
|
// get the drive list on windows...
|
|
|
|
|
if(os.type() == 'Windows_NT' && path == '/'){
|
2016-04-15 02:09:02 +03:00
|
|
|
return new Promise(function(resolve, reject){
|
2015-11-26 02:34:23 +03:00
|
|
|
// NOTE: this is a bit brain-dead but it gets the job done
|
2015-10-12 02:29:08 +03:00
|
|
|
// and faster than fancy modules like drivelist...
|
|
|
|
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
|
|
|
.split('')
|
|
|
|
|
.forEach(function(drive){
|
2015-10-12 02:43:22 +03:00
|
|
|
stat(drive+':/')
|
|
|
|
|
// XXX
|
2015-10-13 02:41:47 +03:00
|
|
|
.catch(function(err){ })
|
2015-10-12 02:43:22 +03:00
|
|
|
.then(function(data){
|
|
|
|
|
data && make(drive+':/')
|
|
|
|
|
|
2015-10-13 02:41:47 +03:00
|
|
|
// resolve when we are done...
|
2015-10-12 02:43:22 +03:00
|
|
|
if(drive == 'Z'){
|
|
|
|
|
resolve()
|
|
|
|
|
}
|
|
|
|
|
})
|
2015-10-12 02:29:08 +03:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// list dirs...
|
|
|
|
|
} else {
|
2016-04-26 04:01:44 +03:00
|
|
|
var _countDirFiles = function(path, file, elem){
|
|
|
|
|
if(that.options.fileCountPattern){
|
|
|
|
|
var i = 0
|
|
|
|
|
glob(path +'/'+ file +'/'+ that.options.fileCountPattern)
|
|
|
|
|
/*
|
|
|
|
|
.on('match', function(){
|
|
|
|
|
i += 1
|
|
|
|
|
elem.attr('count', '('+ i +')')
|
|
|
|
|
})
|
|
|
|
|
*/
|
|
|
|
|
.on('end', function(lst){
|
|
|
|
|
i += 1
|
|
|
|
|
elem.attr('count', lst.length)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
return elem
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-15 02:09:02 +03:00
|
|
|
return new Promise(function(resolve, reject){
|
2015-12-10 06:18:55 +03:00
|
|
|
// XXX should this be a promise???
|
2015-10-12 02:29:08 +03:00
|
|
|
fs.readdir(path, function(err, files){
|
|
|
|
|
// XXX
|
|
|
|
|
if(err){
|
|
|
|
|
reject(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
var res = []
|
|
|
|
|
|
2016-04-25 14:02:52 +03:00
|
|
|
if(that.options.dotDirs){
|
2016-04-27 08:59:13 +03:00
|
|
|
// NOTE: this sometimes gets reordered so we aren't
|
|
|
|
|
// using it... (BUG?)
|
|
|
|
|
// files.splice(0, 0, '.', '..')
|
2016-04-26 04:01:44 +03:00
|
|
|
// NOTE: we are counting these here so as to ensure
|
|
|
|
|
// they are always first and not delayed by some
|
|
|
|
|
// odd delay on a stat...
|
|
|
|
|
_countDirFiles(path, './',
|
|
|
|
|
make(fullpath ? path + './' : './'))
|
|
|
|
|
_countDirFiles(path, '../',
|
|
|
|
|
make(fullpath ? path + '../' : '../'))
|
2016-04-25 14:02:52 +03:00
|
|
|
}
|
|
|
|
|
|
2016-05-09 18:30:16 +03:00
|
|
|
// XXX split out the making stage after the stat stage to
|
|
|
|
|
// be able to sort suff correctly...
|
|
|
|
|
files
|
|
|
|
|
.map(function(file){
|
|
|
|
|
return stat(path +'/'+ file)
|
|
|
|
|
.catch(function(err){
|
2016-04-15 02:09:02 +03:00
|
|
|
make(fullpath
|
|
|
|
|
? path +'/'+ file
|
|
|
|
|
: file, null, true)
|
2016-05-09 18:30:16 +03:00
|
|
|
})
|
|
|
|
|
.then(function(res){
|
|
|
|
|
// can't read stat... (XXX ???)
|
|
|
|
|
if(res == null){
|
|
|
|
|
make(fullpath
|
|
|
|
|
? path +'/'+ file
|
|
|
|
|
: file, null, true)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dir = res.isDirectory()
|
|
|
|
|
var elem = res && make(fullpath
|
|
|
|
|
? path +'/'+ file
|
|
|
|
|
: file + (dir ? '/' : ''),
|
|
|
|
|
null,
|
|
|
|
|
that.options.disableFiles && !dir)
|
|
|
|
|
|
|
|
|
|
// count the number of files...
|
|
|
|
|
// NOTE: we do not care how long it will take
|
|
|
|
|
// so we'll not wait...
|
|
|
|
|
res && dir && _countDirFiles(path, file, elem)
|
|
|
|
|
})
|
|
|
|
|
// NOTE: we are not using promise.all(..) here because it
|
|
|
|
|
// triggers BEFORE the first make(..) is called...
|
|
|
|
|
// ...not sure I fully understand why...
|
|
|
|
|
.then(function(){
|
|
|
|
|
// NOTE: this will get called for all results
|
|
|
|
|
// including ones that generate errors, not
|
|
|
|
|
// sure if this is a bug in .denodeify(..)
|
|
|
|
|
// or by-design though...
|
|
|
|
|
res.push(file)
|
|
|
|
|
if(res.length == files.length){
|
|
|
|
|
resolve()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
2015-10-02 17:33:10 +03:00
|
|
|
})
|
|
|
|
|
})
|
2015-10-12 02:29:08 +03:00
|
|
|
}
|
2015-10-02 17:33:10 +03:00
|
|
|
}
|
|
|
|
|
|
2015-10-02 17:37:18 +03:00
|
|
|
// NOTE: this should work from a chrome app and does not require anything
|
|
|
|
|
// but fs access...
|
2015-10-09 17:14:41 +03:00
|
|
|
// XXX need a default for '/' on windows...
|
2016-04-25 14:02:52 +03:00
|
|
|
// XXX add '.' and '..' support...
|
2015-10-02 17:33:10 +03:00
|
|
|
var listDirBrowser =
|
|
|
|
|
module.listDirBrowser =
|
|
|
|
|
function(path, make){
|
|
|
|
|
path = path.constructor == Array ? path.join('/') : path
|
|
|
|
|
path = /^[a-zA-Z]:/.test(path.trim()) ? path : '/'+path
|
2015-10-09 17:14:41 +03:00
|
|
|
// XXX this is a bit fragile...
|
|
|
|
|
path = /^file:\/\//.test(path.trim()) ? path : 'file:///'+path
|
2015-10-02 17:33:10 +03:00
|
|
|
|
|
|
|
|
var fullpath = false
|
|
|
|
|
|
|
|
|
|
$.get(path)
|
|
|
|
|
// XXX
|
|
|
|
|
.fail(function(err){
|
2015-10-09 17:14:41 +03:00
|
|
|
console.log('!!!', arguments)
|
2015-10-02 17:33:10 +03:00
|
|
|
})
|
|
|
|
|
.done(function(data){
|
2015-10-09 17:14:41 +03:00
|
|
|
// XXX this is very chrome specific...
|
2015-10-02 17:33:10 +03:00
|
|
|
// look for: addRow(name, url, isdir, size, date_modified)
|
2015-10-09 17:14:41 +03:00
|
|
|
$(data)
|
|
|
|
|
.filter('script')
|
|
|
|
|
.toArray()
|
|
|
|
|
.forEach(function(e){
|
|
|
|
|
e = e.innerHTML.split(/.*addRow\((.*)\);/g)
|
|
|
|
|
if(e.length > 1){
|
|
|
|
|
e.filter(function(e, i){ return i % 2 })
|
|
|
|
|
.forEach(function(elem){
|
|
|
|
|
elem = JSON.parse('['+elem+']')
|
|
|
|
|
var file = elem[0]
|
|
|
|
|
|
|
|
|
|
if(file == '..' || file == '.'){
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// do the build...
|
|
|
|
|
make(fullpath
|
|
|
|
|
? path +'/'+ file
|
|
|
|
|
: file + (elem[2] ? '/' : ''))
|
|
|
|
|
})
|
|
|
|
|
}
|
2015-10-02 17:33:10 +03:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//var listDir = module.listDir = listDirBrowser
|
2015-10-13 02:41:47 +03:00
|
|
|
//var listDir = module.listDir = listDirGlob
|
2015-10-02 17:33:10 +03:00
|
|
|
var listDir = module.listDir = listDirfs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
|
|
2015-10-09 17:14:41 +03:00
|
|
|
// XXX for some reason pop does not focus the container dir correctly...
|
|
|
|
|
// ...this is potentially due to the list not being ready yet...
|
2015-11-28 18:15:12 +03:00
|
|
|
// XXX this should be smarter and support other URL schemes...
|
2015-10-02 17:33:10 +03:00
|
|
|
var WalkPrototype = Object.create(browse.Browser.prototype)
|
|
|
|
|
WalkPrototype.options = {
|
2015-11-28 18:15:12 +03:00
|
|
|
// XXX this should be smarter and support other URL schemes...
|
|
|
|
|
pathPrefix: os.type() == 'Windows_NT' ? '' : '/',
|
2015-10-02 17:33:10 +03:00
|
|
|
|
|
|
|
|
fullPathEdit: true,
|
|
|
|
|
traversable: true,
|
|
|
|
|
flat: false,
|
|
|
|
|
|
2015-12-13 09:01:43 +03:00
|
|
|
sortTraversable: 'first',
|
|
|
|
|
|
2015-12-10 00:24:43 +03:00
|
|
|
//actionButton: '⋯',
|
|
|
|
|
actionButton: '⊙',
|
2015-11-27 05:57:06 +03:00
|
|
|
pushButton: false,
|
|
|
|
|
|
2015-10-02 17:33:10 +03:00
|
|
|
list: listDir,
|
2015-12-10 06:56:52 +03:00
|
|
|
|
2015-12-11 07:32:46 +03:00
|
|
|
fileCountPattern: '*',
|
2015-12-13 06:13:13 +03:00
|
|
|
|
|
|
|
|
disableFiles: false,
|
2016-04-25 14:02:52 +03:00
|
|
|
|
|
|
|
|
// enable '.' and '..' dirs...
|
|
|
|
|
dotDirs: true,
|
2015-10-02 17:33:10 +03:00
|
|
|
}
|
|
|
|
|
WalkPrototype.options.__proto__ = browse.Browser.prototype.options
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var Walk =
|
|
|
|
|
module.Walk =
|
|
|
|
|
object.makeConstructor('Walk',
|
|
|
|
|
browse.Browser.__proto__,
|
|
|
|
|
WalkPrototype)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var makeWalk =
|
2015-12-13 06:13:13 +03:00
|
|
|
module.makeWalk = function(elem, path, fileCountPattern, rest){
|
2015-12-10 06:56:52 +03:00
|
|
|
var opts = {}
|
|
|
|
|
if(rest){
|
|
|
|
|
for(var k in rest){
|
|
|
|
|
opts[k] = rest[k]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
opts.path = path
|
|
|
|
|
|
|
|
|
|
opts.fileCountPattern = fileCountPattern == null ?
|
|
|
|
|
WalkPrototype.options.fileCountPattern
|
|
|
|
|
: fileCountPattern
|
|
|
|
|
|
|
|
|
|
var w = Walk(elem, opts)
|
|
|
|
|
|
2015-10-02 17:33:10 +03:00
|
|
|
return w
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-10-13 02:41:47 +03:00
|
|
|
/*********************************************************************/
|
|
|
|
|
|
|
|
|
|
var makeGlobList =
|
|
|
|
|
module.makeGlobList = function(elem, pattern, prepare){
|
|
|
|
|
// XXX
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-10-02 17:33:10 +03:00
|
|
|
/**********************************************************************
|
2016-08-20 22:49:36 +03:00
|
|
|
* vim:set ts=4 sw=4 : */ return module })
|