1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-06-15 23:00:36 +02:00

All: Refactored filesystem sync driver to support mobile

This commit is contained in:
Laurent Cozic
2018-01-17 18:51:15 +00:00
parent f632580eed
commit 1a5c8d126d
7 changed files with 234 additions and 141 deletions

View File

@ -26,66 +26,55 @@ class FileApiDriverLocal {
return output;
}
stat(path) {
return new Promise((resolve, reject) => {
fs.stat(path, (error, s) => {
if (error) {
if (error.code == 'ENOENT') {
resolve(null);
} else {
reject(this.fsErrorToJsError_(error));
}
return;
}
resolve(this.metadataFromStats_(path, s));
});
});
fsDriver() {
if (!FileApiDriverLocal.fsDriver_) throw new Error('FileApiDriverLocal.fsDriver_ not set!');
return FileApiDriverLocal.fsDriver_;
}
statTimeToTimestampMs_(time) {
let m = moment(time, 'YYYY-MM-DDTHH:mm:ss.SSSZ');
if (!m.isValid()) {
throw new Error('Invalid date: ' + time);
async stat(path) {
try {
const s = await this.fsDriver().stat(path);
return this.metadataFromStat_(s);
} catch (error) {
if (error.code == 'ENOENT') return null;
throw this.fsErrorToJsError_(error);
}
return m.toDate().getTime();
}
metadataFromStats_(path, stats) {
metadataFromStat_(stat) {
return {
path: path,
created_time: this.statTimeToTimestampMs_(stats.birthtime),
updated_time: this.statTimeToTimestampMs_(stats.mtime),
created_time_orig: stats.birthtime,
updated_time_orig: stats.mtime,
isDir: stats.isDirectory(),
path: stat.path,
created_time: stat.birthtime.getTime(),
updated_time: stat.mtime.getTime(),
created_time_orig: stat.birthtime,
updated_time_orig: stat.mtime,
isDir: stat.isDirectory(),
};
}
setTimestamp(path, timestampMs) {
return new Promise((resolve, reject) => {
let t = Math.floor(timestampMs / 1000);
fs.utimes(path, t, t, (error) => {
if (error) {
reject(this.fsErrorToJsError_(error));
return;
}
resolve();
});
});
metadataFromStats_(stats) {
let output = [];
for (let i = 0; i < stats.length; i++) {
const mdStat = this.metadataFromStat_(stats[i]);
output.push(mdStat);
}
return output;
}
async setTimestamp(path, timestampMs) {
try {
await this.fsDriver().setTimestamp(path, new Date(timestampMs));
} catch (error) {
throw this.fsErrorToJsError_(error);
}
}
async delta(path, options) {
const itemIds = await options.allItemIdsHandler();
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);
}
const stats = await this.fsDriver().readDirStats(path);
let output = this.metadataFromStats_(stats);
if (!Array.isArray(itemIds)) throw new Error('Delta API not supported - local IDs must be provided');
@ -123,14 +112,8 @@ class FileApiDriverLocal {
async list(path, options) {
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);
}
const stats = await this.fsDriver().readDirStats(path);
const output = this.metadataFromStats_(stats);
return {
items: output,
@ -147,9 +130,11 @@ class FileApiDriverLocal {
try {
if (options.target === 'file') {
output = await fs.copy(path, options.path, { overwrite: true });
//output = await fs.copy(path, options.path, { overwrite: true });
output = await this.fsDriver().copy(path, options.path);
} else {
output = await fs.readFile(path, options.encoding);
//output = await fs.readFile(path, options.encoding);
output = await this.fsDriver().readFile(path, options.encoding);
}
} catch (error) {
if (error.code == 'ENOENT') return null;
@ -159,78 +144,107 @@ class FileApiDriverLocal {
return output;
}
mkdir(path) {
return new Promise((resolve, reject) => {
fs.exists(path, (exists) => {
if (exists) {
resolve();
return;
}
async mkdir(path) {
if (await this.fsDriver().exists(path)) return;
try {
await this.fsDriver().mkdir(path);
} catch (error) {
throw this.fsErrorToJsError_(error);
}
// return new Promise((resolve, reject) => {
// fs.exists(path, (exists) => {
// if (exists) {
// resolve();
// return;
// }
fs.mkdirp(path, (error) => {
if (error) {
reject(this.fsErrorToJsError_(error));
} else {
resolve();
}
});
});
});
// fs.mkdirp(path, (error) => {
// if (error) {
// reject(this.fsErrorToJsError_(error));
// } else {
// resolve();
// }
// });
// });
// });
}
async put(path, content, options = null) {
if (!options) options = {};
if (options.source === 'file') content = await fs.readFile(options.path);
try {
if (options.source === 'file') {
await this.fsDriver().copy(options.path, path);
return;
}
await this.fsDriver().writeFile(path, content, 'utf8');
} catch (error) {
throw this.fsErrorToJsError_(error);
}
return new Promise((resolve, reject) => {
fs.writeFile(path, content, function(error) {
if (error) {
reject(this.fsErrorToJsError_(error));
} else {
resolve();
}
});
});
// if (!options) options = {};
// if (options.source === 'file') content = await fs.readFile(options.path);
// return new Promise((resolve, reject) => {
// fs.writeFile(path, content, function(error) {
// if (error) {
// reject(this.fsErrorToJsError_(error));
// } 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 {
reject(this.fsErrorToJsError_(error));
}
} else {
resolve();
}
});
});
async delete(path) {
try {
await this.fsDriver().unlink(path);
} catch (error) {
throw this.fsErrorToJsError_(error);
}
// 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 {
// reject(this.fsErrorToJsError_(error));
// }
// } else {
// resolve();
// }
// });
// });
}
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;
}
throw this.fsErrorToJsError_(error);
}
}
return this.fsDriver().move(oldPath, newPath);
throw lastError;
// 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;
// }
// throw this.fsErrorToJsError_(error);
// }
// }
// throw lastError;
}
format() {