joplin/ReactNativeClient/lib/file-api-driver-local.js

179 lines
3.6 KiB
JavaScript
Raw Normal View History

2017-07-02 10:34:07 +00:00
import fs from 'fs-extra';
2017-06-24 18:06:28 +00:00
import { promiseChain } from 'lib/promise-utils.js';
2017-06-11 21:11:14 +00:00
import moment from 'moment';
2017-07-02 10:34:07 +00:00
import { time } from 'lib/time-utils.js';
2017-06-11 21:11:14 +00:00
class FileApiDriverLocal {
2017-07-03 18:58:01 +00:00
fsErrorToJsError_(error) {
let msg = error.toString();
let output = new Error(msg);
if (error.code) output.code = error.code;
return output;
}
2017-06-11 21:11:14 +00:00
stat(path) {
return new Promise((resolve, reject) => {
fs.stat(path, (error, s) => {
if (error) {
2017-06-14 23:14:15 +00:00
if (error.code == 'ENOENT') {
resolve(null);
} else {
2017-07-03 18:58:01 +00:00
reject(this.fsErrorToJsError_(error));
2017-06-14 23:14:15 +00:00
}
2017-06-11 21:11:14 +00:00
return;
}
2017-06-14 23:14:15 +00:00
resolve(this.metadataFromStats_(path, s));
2017-06-11 21:11:14 +00:00
});
});
}
2017-06-27 19:48:01 +00:00
statTimeToTimestampMs_(time) {
2017-06-11 21:11:14 +00:00
let m = moment(time, 'YYYY-MM-DDTHH:mm:ss.SSSZ');
if (!m.isValid()) {
throw new Error('Invalid date: ' + time);
}
2017-06-27 19:48:01 +00:00
return m.toDate().getTime();
2017-06-11 21:11:14 +00:00
}
2017-06-12 21:56:27 +00:00
metadataFromStats_(path, stats) {
2017-06-11 21:11:14 +00:00
return {
2017-06-12 21:56:27 +00:00
path: path,
2017-06-27 19:48:01 +00:00
created_time: this.statTimeToTimestampMs_(stats.birthtime),
updated_time: this.statTimeToTimestampMs_(stats.mtime),
2017-06-18 22:06:10 +00:00
created_time_orig: stats.birthtime,
updated_time_orig: stats.mtime,
2017-06-11 21:11:14 +00:00
isDir: stats.isDirectory(),
};
}
2017-06-27 19:48:01 +00:00
setTimestamp(path, timestampMs) {
2017-06-12 21:56:27 +00:00
return new Promise((resolve, reject) => {
2017-06-27 19:48:01 +00:00
let t = Math.floor(timestampMs / 1000);
fs.utimes(path, t, t, (error) => {
2017-06-12 21:56:27 +00:00
if (error) {
2017-07-03 18:58:01 +00:00
reject(this.fsErrorToJsError_(error));
2017-06-12 21:56:27 +00:00
return;
}
resolve();
});
});
}
2017-07-02 10:34:07 +00:00
async list(path, options) {
2017-07-03 18:58:01 +00:00
try {
let items = await fs.readdir(path);
let output = [];
for (let i = 0; i < items.length; i++) {
let stat = await this.stat(path + '/' + items[i]);
if (!stat) continue; // Has been deleted between the readdir() call and now
stat.path = items[i];
output.push(stat);
}
2017-06-11 21:11:14 +00:00
2017-07-03 18:58:01 +00:00
return {
items: output,
hasMore: false,
context: null,
};
} catch(error) {
throw this.fsErrorToJsError_(error);
}
2017-06-11 21:11:14 +00:00
}
2017-07-02 12:02:07 +00:00
async get(path, options) {
let output = null;
try {
if (options.encoding == 'binary') {
output = fs.readFile(path);
} else {
output = fs.readFile(path, options.encoding);
}
} catch (error) {
if (error.code == 'ENOENT') return null;
2017-07-03 18:58:01 +00:00
throw this.fsErrorToJsError_(error);
2017-07-02 12:02:07 +00:00
}
return output;
2017-06-11 21:11:14 +00:00
}
mkdir(path) {
return new Promise((resolve, reject) => {
fs.exists(path, (exists) => {
if (exists) {
resolve();
return;
}
const mkdirp = require('mkdirp');
mkdirp(path, (error) => {
if (error) {
2017-07-03 18:58:01 +00:00
reject(this.fsErrorToJsError_(error));
2017-06-11 21:11:14 +00:00
} else {
resolve();
}
});
});
});
}
put(path, content) {
return new Promise((resolve, reject) => {
fs.writeFile(path, content, function(error) {
if (error) {
2017-07-03 18:58:01 +00:00
reject(this.fsErrorToJsError_(error));
2017-06-11 21:11:14 +00:00
} else {
resolve();
}
});
});
}
delete(path) {
return new Promise((resolve, reject) => {
fs.unlink(path, function(error) {
if (error) {
if (error && error.code == 'ENOENT') {
// File doesn't exist - it's fine
resolve();
} else {
2017-07-03 18:58:01 +00:00
reject(this.fsErrorToJsError_(error));
2017-06-11 21:11:14 +00:00
}
} else {
resolve();
}
});
});
}
2017-07-02 10:34:07 +00:00
async move(oldPath, newPath) {
let lastError = null;
for (let i = 0; i < 5; i++) {
try {
let output = await fs.move(oldPath, newPath, { overwrite: true });
return output;
} catch (error) {
lastError = error;
// Normally cannot happen with the `overwrite` flag but sometime it still does.
// In this case, retry.
if (error.code == 'EEXIST') {
await time.sleep(1);
continue;
}
2017-07-03 18:58:01 +00:00
throw this.fsErrorToJsError_(error);
2017-07-02 10:34:07 +00:00
}
}
throw lastError;
2017-06-11 21:11:14 +00:00
}
2017-06-13 20:58:17 +00:00
format() {
throw new Error('Not supported');
}
2017-06-11 21:11:14 +00:00
}
export { FileApiDriverLocal };