control-freak-ide/server/nodejs/nxapp/manager/FileManager.js
plastic-hub-dev-node-saturn 538369cff7 latest
2021-05-12 18:35:18 +02:00

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);
}
}
}
});
});