619 lines
17 KiB
JavaScript
619 lines
17 KiB
JavaScript
define([
|
|
"dcl/dcl",
|
|
'dojo/has',
|
|
'nxapp/manager/ManagerBase',
|
|
'nxapp/utils/_LogMixin',
|
|
'xide/types',
|
|
'xide/factory',
|
|
"dojo/node!path",
|
|
"dojo/node!fs",
|
|
"dojo/node!child_process",
|
|
"dojo/node!chokidar"
|
|
], function (dcl, has, ManagerBase, _LogMixin, types, factory, path, fs, child_process, chokidar) {
|
|
|
|
var isWindows = has('windows');
|
|
var isARM = has('arm');
|
|
isWindows = true;
|
|
var useWatcher = isWindows === true || isARM === true;
|
|
var useChokidar = true;
|
|
var debug = false;
|
|
|
|
return dcl([ManagerBase, _LogMixin], {
|
|
declaredClass: "nxapp.manager.FileManager",
|
|
watcher: null,
|
|
resolve: function (_path) {
|
|
var result = "";
|
|
var _libRoot = path.resolve(dojoConfig.libRoot);
|
|
var _clientRoot = path.resolve(dojoConfig.clientRoot);
|
|
if (fs.existsSync(path.resolve(_path))) {
|
|
return _path;
|
|
}
|
|
if (_path[0] == '/') {
|
|
_path = path.resolve(_path);
|
|
}
|
|
else if (path.resolve(_libRoot + '/' + _path)) {
|
|
result = path.resolve(_libRoot + '/' + _path);
|
|
}
|
|
else if (fs.existsSync(path.resolve(_path))) {
|
|
//try absolute
|
|
result = path.resolve(_path);
|
|
}
|
|
else if (path.resolve(_clientRoot + '/' + _path)) {
|
|
//try client root
|
|
result = path.resolve(_clientRoot + '/' + _path);
|
|
}
|
|
|
|
return result;
|
|
},
|
|
watch: function (path, watch) {
|
|
try {
|
|
if (fs.existsSync(path) && watch) {
|
|
if (this.watcher && this.watcher.add) {
|
|
this.watcher.add(path);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
}
|
|
},
|
|
initChokidar: function (profile) {
|
|
for (var i = 0; i < profile.watchr.paths.length; i++) {
|
|
var _path = profile.watchr.paths[i];
|
|
var _libRoot = path.resolve(dojoConfig.libRoot);
|
|
var _clientRoot = path.resolve(dojoConfig.clientRoot);
|
|
|
|
if (_path[0] == '/') {
|
|
_path = path.resolve(_path);
|
|
}
|
|
else if (path.resolve(_path) && fs.existsSync(_path)) {
|
|
//try lib root
|
|
profile.watchr.paths[i] = path.resolve(_path);
|
|
}
|
|
else if (fs.existsSync(path.resolve(_libRoot + '/' + _path))) {
|
|
//try lib root
|
|
profile.watchr.paths[i] = path.resolve(_libRoot + '/' + _path);
|
|
}
|
|
else if (fs.existsSync(path.resolve(_path))) {
|
|
//try absolute
|
|
profile.watchr.paths[i] = path.resolve(_path);
|
|
}
|
|
else if (path.resolve(_clientRoot + '/' + _path)) {
|
|
//try client root
|
|
profile.watchr.paths[i] = path.resolve(_clientRoot + '/' + _path);
|
|
}
|
|
}
|
|
var thiz = this;
|
|
|
|
function modulePath(_path) {
|
|
_path = _path.replace(dojoConfig.libRoot + '/', '');
|
|
if (_path.startsWith('/')) {
|
|
_path = _path.replace('/', '');
|
|
}
|
|
return _path;
|
|
}
|
|
var watcher = chokidar.watch(profile.watchr.paths, {
|
|
ignored: function (path) {
|
|
if (path.indexOf('metadata') !== -1) {
|
|
return true;
|
|
};
|
|
if (path.indexOf('.git') !== -1) {
|
|
return true;
|
|
};
|
|
return false;
|
|
},
|
|
persistent: true,
|
|
ignoreInitial: true,
|
|
awaitWriteFinish: true
|
|
});
|
|
|
|
|
|
watcher.on('addDir', function (filePath) {
|
|
watcher.add(filePath);
|
|
debug && console.log('add dir ' + filePath);
|
|
factory.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: filePath,
|
|
modulePath: modulePath(filePath)
|
|
}, thiz);
|
|
});
|
|
|
|
watcher.on('add', function (filePath) {
|
|
debug && console.log('add file' + filePath);
|
|
factory.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: filePath,
|
|
modulePath: modulePath(filePath),
|
|
type: 'added'
|
|
}, thiz);
|
|
});
|
|
|
|
watcher.on('unlinkDir', function (filePath) {
|
|
watcher.unwatch(filePath);
|
|
factory.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: filePath,
|
|
modulePath: modulePath(filePath),
|
|
type: 'delete'
|
|
}, thiz);
|
|
});
|
|
|
|
watcher.on('change', function (filePath) {
|
|
debug && console.log('changed ' + filePath);
|
|
thiz.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: filePath,
|
|
modulePath: modulePath(filePath),
|
|
type: 'changed'
|
|
}, thiz);
|
|
});
|
|
|
|
|
|
watcher.on('raw', function (event, path, details) {
|
|
//console.log('Raw event info:', [event, path, details]);
|
|
if (event === 'rename') {
|
|
try {
|
|
var fs = fs.statSync(details.watchedPath);
|
|
} catch (e) {
|
|
if (details.watchedPath.indexOf(path) !== -1) {
|
|
debug && console.error('removed :' + details.watchedPath);
|
|
factory.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: details.watchedPath,
|
|
modulePath: details.watchedPath.replace(dojoConfig.libRoot, ''),
|
|
type: 'delete'
|
|
}, thiz);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
this.watcher = watcher;
|
|
},
|
|
/**
|
|
* Plain Watchr version
|
|
* @param profile
|
|
*/
|
|
initWindows_Watchr: function (profile) {
|
|
/*
|
|
for(var i = 0 ; i < profile.watchr.paths.length ; i++){
|
|
|
|
if(profile.watchr.paths[i][0]=='/'){
|
|
profile.watchr.paths[i]= path.resolve(profile.watchr.paths[i]);
|
|
}else{
|
|
profile.watchr.paths[i]= path.resolve(dojoConfig.root + '/' +profile.watchr.paths[i]);
|
|
}
|
|
|
|
|
|
}
|
|
*/
|
|
for (var i = 0; i < profile.watchr.paths.length; i++) {
|
|
|
|
var _path = profile.watchr.paths[i];
|
|
var _libRoot = path.resolve(dojoConfig.libRoot);
|
|
var _clientRoot = path.resolve(dojoConfig.clientRoot);
|
|
|
|
if (_path[0] == '/') {
|
|
_path = path.resolve(_path);
|
|
|
|
}
|
|
else if (path.resolve(_libRoot + '/' + _path)) {
|
|
//try lib root
|
|
profile.watchr.paths[i] = path.resolve(_libRoot + '/' + _path);
|
|
}
|
|
else if (fs.existsSync(path.resolve(_path))) {
|
|
//try absolute
|
|
profile.watchr.paths[i] = path.resolve(_path);
|
|
}
|
|
else if (path.resolve(_clientRoot + '/' + _path)) {
|
|
//try client root
|
|
profile.watchr.paths[i] = path.resolve(_clientRoot + '/' + _path);
|
|
}
|
|
}
|
|
|
|
|
|
//console.dir(profile.watchr.paths);
|
|
|
|
|
|
_.each(profile.watchr.paths, function (path) {
|
|
//debug && console.log('start watching ' + path);
|
|
});
|
|
|
|
var thiz = this;
|
|
|
|
watchr.watch({
|
|
paths: profile.watchr.paths,
|
|
interval: 500,
|
|
listeners: {
|
|
log: function (logLevel) {
|
|
},
|
|
error: function (err) {
|
|
console.log('an error occured:', err);
|
|
},
|
|
watching: function (err, watcherInstance, isWatching) {
|
|
if (err) {
|
|
debug && console.error("watching the path " + watcherInstance.path + " failed with error", err);
|
|
} else {
|
|
debug && console.error("watching the path " + watcherInstance.path + " completed");
|
|
}
|
|
},
|
|
change: function (changeType, filePath, fileCurrentStat, filePreviousStat) {
|
|
if (!filePath) {
|
|
return;
|
|
}
|
|
|
|
debug && console.log('file changed: ' + filePath.replace(dojoConfig.libRoot, '') + ' actual file' + filePath);
|
|
factory.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: filePath,
|
|
modulePath: filePath.replace(dojoConfig.libRoot, '')
|
|
}, thiz);
|
|
|
|
}
|
|
},
|
|
next: function (err, watchers) {
|
|
if (err) {
|
|
return console.log("watching everything failed with error", err);
|
|
} else {
|
|
console.log('watching everything completed');
|
|
}
|
|
// Close watchers after 60 seconds
|
|
/*
|
|
setTimeout(function(){
|
|
var i;
|
|
console.log('Stop watching our paths');
|
|
for ( i=0; i<watchers.length; i++ ) {
|
|
watchers[i].close();
|
|
}
|
|
},60*1000);
|
|
*/
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* Windows iNotify version: incomplete
|
|
*/
|
|
initWindows: function (profile) {
|
|
|
|
function run_cmd(cmd, args, cb, end) {
|
|
|
|
var spawn = child_process.spawn,
|
|
child = spawn(cmd, args),
|
|
me = this;
|
|
|
|
child.stdout.on('data', function (buffer) {
|
|
cb(me, buffer);
|
|
});
|
|
|
|
child.stdout.on('end', end);
|
|
}
|
|
|
|
for (var i = 0; i < profile.watchr.paths.length; i++) {
|
|
|
|
var _path = profile.watchr.paths[i];
|
|
var _libRoot = path.resolve(dojoConfig.libRoot);
|
|
var _clientRoot = path.resolve(dojoConfig.clientRoot);
|
|
|
|
if (_path[0] == '/') {
|
|
_path = path.resolve(_path);
|
|
|
|
}
|
|
else if (path.resolve(_libRoot + '/' + _path)) {
|
|
//try lib root
|
|
profile.watchr.paths[i] = path.resolve(_libRoot + '/' + _path);
|
|
}
|
|
else if (fs.existsSync(path.resolve(_path))) {
|
|
//try absolute
|
|
profile.watchr.paths[i] = path.resolve(_path);
|
|
}
|
|
else if (path.resolve(_clientRoot + '/' + _path)) {
|
|
//try client root
|
|
profile.watchr.paths[i] = path.resolve(_clientRoot + '/' + _path);
|
|
}
|
|
}
|
|
|
|
|
|
//console.dir(profile.watchr.paths);
|
|
|
|
|
|
var notifyPath = path.resolve(global.cwd + '/inotifywait.exe');
|
|
|
|
var path1 = profile.watchr.paths[0];
|
|
|
|
function notify(path, event) {
|
|
//console.log('file changed : ' +event + ' path:' + path);
|
|
}
|
|
|
|
|
|
var foo = new run_cmd(
|
|
//'--format={event:\'%e\',path:\'%w\'}'
|
|
notifyPath, ['-r', '-m', '-q', '--format=%w|%e|%f', path1],
|
|
|
|
function (me, buffer) {
|
|
|
|
me.stdout = "";
|
|
var str = buffer.toString(), lines = str.split(/(\r?\n)/g);
|
|
for (var i = 0; i < lines.length; i++) {
|
|
// Process the line, noting it might be incomplete.
|
|
var line = lines[i];
|
|
if (line && line.length > 5) {
|
|
var parts = line.split('|');
|
|
if (parts.length == 3) {
|
|
notify(path.resolve(parts[0] + '/' + parts[2]), parts[1]);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
function () {
|
|
console.log('end : ' + foo.stdout);
|
|
}
|
|
);
|
|
},
|
|
/**
|
|
* Mac/Linux version
|
|
* @param profile
|
|
* @returns {*}
|
|
*/
|
|
init: function (profile) {
|
|
|
|
if (useChokidar) {
|
|
return this.initChokidar(profile);
|
|
}
|
|
|
|
if (isWindows || isARM) {
|
|
return this.initWindows_Watchr(profile);
|
|
//return this.initWindows(profile);
|
|
}
|
|
|
|
///return this.initWindows_Watchr(profile);
|
|
var thiz = this;
|
|
var _req = require;
|
|
try {
|
|
_req(['dojo/node!gbaumgart.inotify-plusplus'], function (notify) {
|
|
thiz.initLinux(profile, notify);
|
|
});
|
|
} catch (e) {
|
|
debug && console.error('cant load inotify, proceed with watchr ' + e.message);
|
|
return this.initWindows_Watchr(profile);
|
|
}
|
|
|
|
},
|
|
initLinux: function (profile, inotify) {
|
|
|
|
for (var i = 0; i < profile.watchr.paths.length; i++) {
|
|
|
|
var _path = profile.watchr.paths[i];
|
|
var _libRoot = path.resolve(dojoConfig.libRoot);
|
|
var _clientRoot = path.resolve(dojoConfig.clientRoot);
|
|
|
|
if (_path[0] == '/') {
|
|
_path = path.resolve(_path);
|
|
|
|
}
|
|
else if (path.resolve(_libRoot + '/' + _path)) {
|
|
//try lib root
|
|
profile.watchr.paths[i] = path.resolve(_libRoot + '/' + _path);
|
|
}
|
|
else if (fs.existsSync(path.resolve(_path))) {
|
|
//try absolute
|
|
profile.watchr.paths[i] = path.resolve(_path);
|
|
}
|
|
else if (path.resolve(_clientRoot + '/' + _path)) {
|
|
//try client root
|
|
profile.watchr.paths[i] = path.resolve(_clientRoot + '/' + _path);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var thiz = this;
|
|
|
|
|
|
|
|
|
|
function readDir(start, callback) {
|
|
// Use lstat to resolve symlink if we are passed a symlink
|
|
fs.lstat(start, function (err, stat) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
var found = { dirs: [], files: [] },
|
|
total = 0,
|
|
processed = 0;
|
|
function isDir(abspath) {
|
|
fs.stat(abspath, function (err, stat) {
|
|
|
|
if (stat.isDirectory()) {
|
|
found.dirs.push(abspath);
|
|
// If we found a directory, recurse!
|
|
readDir(abspath, function (err, data) {
|
|
found.dirs = found.dirs.concat(data.dirs);
|
|
found.files = found.files.concat(data.files);
|
|
if (++processed == total) {
|
|
callback(null, found);
|
|
}
|
|
});
|
|
} else {
|
|
/*
|
|
found.files.push(abspath);
|
|
if(++processed == total) {
|
|
callback(null, found);
|
|
}
|
|
*/
|
|
}
|
|
});
|
|
}
|
|
// Read through all the files in this directory
|
|
if (stat.isDirectory()) {
|
|
fs.readdir(start, function (err, files) {
|
|
total = files.length;
|
|
if (total === 0) {
|
|
callback(null, found);
|
|
}
|
|
for (var x = 0, l = files.length; x < l; x++) {
|
|
isDir(path.join(start, files[x]));
|
|
if (total === 0) {
|
|
callback(null, found);
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
return callback(new Error("path: " + start + " is not a directory"));
|
|
}
|
|
});
|
|
}
|
|
|
|
var _walk = function (dir) {
|
|
var results = [];
|
|
if (fs.existsSync(dir)) {
|
|
var list = fs.readdirSync(dir);
|
|
|
|
list.forEach(function (file) {
|
|
file = dir + '/' + file;
|
|
var stat = fs.statSync(file);
|
|
if (stat && stat.isDirectory()) {
|
|
results.push(file);
|
|
results = results.concat(_walk(file));
|
|
}
|
|
});
|
|
}
|
|
return results
|
|
};
|
|
|
|
var directive = (function () {
|
|
// private variables
|
|
var count = 0,
|
|
validate_watch,
|
|
move,
|
|
cookies = {};
|
|
|
|
// shared method
|
|
move = function (ev) {
|
|
var pre = cookies[ev.cookie];
|
|
if (pre) {
|
|
|
|
cookies[ev.cookie] = undefined;
|
|
delete cookies[ev.cookie];
|
|
} else {
|
|
// expires the cookie if the move doesn't complete in this watch
|
|
cookies[ev.cookie] = ev;
|
|
setTimeout(function () {
|
|
cookies[ev.cookie] = undefined;
|
|
delete cookies[ev.cookie];
|
|
}, 500);
|
|
}
|
|
};
|
|
|
|
// will listen to three events
|
|
// multiple events may fire at the same time
|
|
return {
|
|
all_events: function (ev) {
|
|
// example ev: { watch: '/path/to/watch', masks: '["access", "move_to"]', cookie: 1, name: 'name_of_file' }
|
|
//validate_watch();
|
|
|
|
//console.log("all_events : file changed! path " + path.resolve(ev.watch + '/' +ev.name) + ' mask:' + ev.masks.toString()) ;
|
|
|
|
count += 1;
|
|
if (!ev || !ev.name || !ev.name.indexOf) {
|
|
//console.log('a0');
|
|
return;
|
|
}
|
|
if (ev.name.indexOf('.git') != -1 || ev.name.indexOf('.tmp') != -1) {
|
|
//console.log('a1');
|
|
return;
|
|
}
|
|
if (ev.name.indexOf('_jb_old_') != -1 || ev.name.indexOf('_jb_bak_') != -1) {
|
|
//console.log('a2');
|
|
return;
|
|
}
|
|
|
|
if (ev.masks.toString().indexOf('access') != -1) {
|
|
//console.log('a3');
|
|
return;
|
|
}
|
|
|
|
if (ev.masks.toString().indexOf('moved_to') != -1) {
|
|
//console.log('a4');
|
|
//console.log('moved to');
|
|
//console.log("xxx masks were just activated: '" + ev.masks.toString() + "' for '" + ev.name + "'.");
|
|
//return;
|
|
}
|
|
|
|
//console.log("file changed! path " + path.resolve(ev.watch + '/' +ev.name));
|
|
|
|
//console.log("These masks were just activated: '" + ev.masks.toString() + "' for '" + ev.name + "'.");
|
|
//console.log("all_events : file changed! path " + path.resolve(ev.watch + '/' +ev.name) + ' mask:' + ev.masks.toString()) ;
|
|
|
|
|
|
|
|
var _path = path.resolve(ev.watch + '/' + ev.name);
|
|
var mask = ev.masks.toString().replace('all_events,', '');
|
|
var type = 'changed';
|
|
if (mask.indexOf('delete') !== -1) {
|
|
type = 'deleted';
|
|
}
|
|
|
|
if (_path) {
|
|
factory.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: _path,
|
|
modulePath: _path.replace(dojoConfig.libRoot, ''),
|
|
type: type
|
|
}, thiz);
|
|
}
|
|
|
|
},
|
|
close_write: function (ev) {
|
|
|
|
//console.log("close-write : file changed! path " + path.resolve(ev.watch + '/' +ev.name) + ' mask ' + ev.masks.toString());
|
|
|
|
count += 1;
|
|
|
|
if (ev.name.indexOf('.git') != -1 || ev.name.indexOf('.tmp') != -1) {
|
|
return;
|
|
}
|
|
if (ev.name.indexOf('_jb_old_') != -1 || ev.name.indexOf('_jb_bak_') != -1) {
|
|
return;
|
|
}
|
|
|
|
if (ev.masks.toString().indexOf('access') != -1) {
|
|
return;
|
|
}
|
|
|
|
if (ev.masks.toString().indexOf('moved_to') != -1) {
|
|
// console.log("xxx masks were just activated: '" + ev.masks.toString() + "' for '" + ev.name + "'.");
|
|
return;
|
|
}
|
|
|
|
//console.log("These masks were just activated: '" + ev.masks.toString() + "' for '" + ev.name + "'.");
|
|
|
|
//console.log('close write',ev);
|
|
var _path = path.resolve(ev.watch + '/' + ev.name);
|
|
if (_path) {
|
|
//console.log('-file changed');
|
|
factory.publish(types.EVENTS.ON_FILE_CHANGED, {
|
|
path: _path,
|
|
modulePath: _path.replace(dojoConfig.libRoot, '')
|
|
}, thiz);
|
|
}
|
|
},
|
|
access: true,
|
|
moved_to: true,
|
|
moved_from: true,
|
|
"delete": true
|
|
};
|
|
}());
|
|
|
|
var Inotify = inotify.create(false);
|
|
|
|
for (var j = 0; j < profile.watchr.paths.length; j++) {
|
|
var dir = profile.watchr.paths[j];
|
|
|
|
if (!fs.existsSync(dir)) {
|
|
debug && console.error('directory : ' + dir + ' doesnt exists');
|
|
continue;
|
|
}
|
|
debug && console.log('start watching ' + dir);
|
|
var _results = _walk(dir);
|
|
Inotify.watch(directive, dir);
|
|
for (var i = 0; i < _results.length; i++) {
|
|
var _dir = _results[i];
|
|
/*console.log('start watching ' + _dir);*/
|
|
Inotify.watch(directive, _dir);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|