keeweb/app/scripts/storage/storage-file.js

162 lines
4.9 KiB
JavaScript
Raw Normal View History

2015-12-02 21:39:40 +01:00
'use strict';
2017-01-31 07:50:28 +01:00
const StorageBase = require('./storage-base');
const Launcher = require('../comp/launcher');
2015-12-02 21:39:40 +01:00
2017-01-31 07:50:28 +01:00
const fileWatchers = {};
2016-02-06 11:59:57 +01:00
2017-01-31 07:50:28 +01:00
const StorageFile = StorageBase.extend({
2015-12-02 21:39:40 +01:00
name: 'file',
2016-03-12 12:22:35 +01:00
icon: 'hdd-o',
2015-12-02 21:39:40 +01:00
enabled: !!Launcher,
2016-03-13 17:08:25 +01:00
system: true,
2016-08-21 18:07:59 +02:00
backup: true,
2015-12-02 21:39:40 +01:00
2016-03-12 17:49:52 +01:00
load: function(path, opts, callback) {
2016-03-27 09:06:23 +02:00
this.logger.debug('Load', path);
2017-01-31 07:50:28 +01:00
const ts = this.logger.ts();
2017-02-01 02:37:43 +01:00
const onError = e => {
2016-03-27 09:06:23 +02:00
this.logger.error('Error reading local file', path, e);
2017-02-01 02:37:43 +01:00
if (callback) {
callback(e, null);
}
};
Launcher.readFile(path, data => {
Launcher.statFile(path, stat => {
const rev = stat.mtime.getTime().toString();
this.logger.debug('Loaded', path, rev, this.logger.ts(ts));
if (callback) {
callback(null, data.buffer, { rev: rev });
}
}, onError);
}, onError);
2015-12-02 21:39:40 +01:00
},
2016-03-12 17:49:52 +01:00
stat: function(path, opts, callback) {
2016-03-27 09:06:23 +02:00
this.logger.debug('Stat', path);
2017-01-31 07:50:28 +01:00
const ts = this.logger.ts();
2017-02-01 02:37:43 +01:00
Launcher.statFile(path, stat => {
2016-03-27 09:06:23 +02:00
this.logger.debug('Stat done', path, this.logger.ts(ts));
2017-02-01 02:37:43 +01:00
if (callback) {
const fileRev = stat.mtime.getTime().toString();
callback(null, { rev: fileRev });
}
}, e => {
2016-03-27 09:06:23 +02:00
this.logger.error('Error stat local file', path, e);
2017-02-01 02:37:43 +01:00
if (callback) {
callback(e, null);
2016-02-06 11:59:57 +01:00
}
2017-02-01 02:37:43 +01:00
});
2016-02-06 11:59:57 +01:00
},
2016-03-12 17:49:52 +01:00
save: function(path, opts, data, callback, rev) {
2016-03-27 09:06:23 +02:00
this.logger.debug('Save', path, rev);
2017-01-31 07:50:28 +01:00
const ts = this.logger.ts();
2017-02-01 02:37:43 +01:00
const onError = e => {
this.logger.error('Error writing local file', path, e);
if (callback) {
callback(e);
}
};
const write = () => {
Launcher.writeFile(path, data, () => {
Launcher.statFile(path, stat => {
2017-02-03 00:48:20 +01:00
const newRev = stat.mtime.getTime().toString();
2017-02-01 02:37:43 +01:00
this.logger.debug('Saved', path, this.logger.ts(ts));
if (callback) {
callback(undefined, { rev: newRev });
}
}, onError);
}, onError);
};
if (rev) {
Launcher.statFile(path, stat => {
2017-02-03 00:48:20 +01:00
const fileRev = stat.mtime.getTime().toString();
2017-02-01 02:37:43 +01:00
if (fileRev !== rev) {
this.logger.debug('Save mtime differs', rev, fileRev);
if (callback) {
callback({ revConflict: true }, { rev: fileRev });
2016-02-06 11:59:57 +01:00
}
}
2017-02-01 02:37:43 +01:00
write();
}, onError);
} else {
write();
2015-12-02 21:39:40 +01:00
}
2016-02-06 11:59:57 +01:00
},
2016-08-21 18:07:59 +02:00
mkdir: function(path, callback) {
this.logger.debug('Make dir', path);
2017-01-31 07:50:28 +01:00
const ts = this.logger.ts();
2017-02-01 02:37:43 +01:00
Launcher.mkdir(path, () => {
2016-08-21 18:07:59 +02:00
this.logger.debug('Made dir', path, this.logger.ts(ts));
2017-02-01 02:37:43 +01:00
if (callback) {
callback();
}
}, e => {
2016-08-21 18:07:59 +02:00
this.logger.error('Error making local dir', path, e);
2017-02-01 02:37:43 +01:00
if (callback) {
callback(e);
}
});
2016-08-21 18:07:59 +02:00
},
2016-02-06 11:59:57 +01:00
watch: function(path, callback) {
2017-01-31 07:50:28 +01:00
const names = Launcher.parsePath(path);
2016-02-06 11:59:57 +01:00
if (!fileWatchers[names.dir]) {
2016-03-27 09:06:23 +02:00
this.logger.debug('Watch dir', names.dir);
2017-01-31 07:50:28 +01:00
const fsWatcher = Launcher.createFsWatcher(names.dir);
if (fsWatcher) {
fsWatcher.on('change', this.fsWatcherChange.bind(this, names.dir));
fileWatchers[names.dir] = {
fsWatcher: fsWatcher,
callbacks: []
};
}
2016-02-06 11:59:57 +01:00
}
const fsWatcher = fileWatchers[names.dir];
fsWatcher && fsWatcher.callbacks.push({
file: names.file,
callback: callback
});
2016-02-06 11:59:57 +01:00
},
unwatch: function(path) {
2017-01-31 07:50:28 +01:00
const names = Launcher.parsePath(path);
const watcher = fileWatchers[names.dir];
2016-02-06 11:59:57 +01:00
if (watcher) {
2017-01-31 07:50:28 +01:00
const ix = watcher.callbacks.findIndex(cb => cb.file === names.file);
2016-02-06 11:59:57 +01:00
if (ix >= 0) {
watcher.callbacks.splice(ix, 1);
}
if (!watcher.callbacks.length) {
2016-03-27 09:06:23 +02:00
this.logger.debug('Stop watch dir', names.dir);
2017-02-05 01:12:01 +01:00
watcher.fsWatcher.close();
2016-02-06 11:59:57 +01:00
delete fileWatchers[names.dir];
}
}
},
fsWatcherChange: function(dirname, evt, fileName) {
2017-01-31 07:50:28 +01:00
const watcher = fileWatchers[dirname];
2016-02-06 11:59:57 +01:00
if (watcher) {
2016-07-17 13:30:38 +02:00
watcher.callbacks.forEach(cb => {
2016-02-06 11:59:57 +01:00
if (cb.file === fileName && typeof cb.callback === 'function') {
2016-07-17 13:30:38 +02:00
this.logger.debug('File changed', dirname, evt, fileName);
2016-02-06 11:59:57 +01:00
cb.callback();
}
});
}
2015-12-02 21:39:40 +01:00
}
2016-03-27 09:06:23 +02:00
});
2015-12-02 21:39:40 +01:00
2016-03-27 09:46:43 +02:00
module.exports = new StorageFile();