mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Updated tools
This commit is contained in:
parent
4b55fefcb1
commit
ab8c66a361
@ -7,4 +7,4 @@ rsync -a "$ROOT_DIR/../ReactNativeClient/lib/" "$BUILD_DIR/lib/"
|
|||||||
rsync -a "$ROOT_DIR/build/locales/" "$BUILD_DIR/locales/"
|
rsync -a "$ROOT_DIR/build/locales/" "$BUILD_DIR/locales/"
|
||||||
mkdir -p "$BUILD_DIR/data"
|
mkdir -p "$BUILD_DIR/data"
|
||||||
|
|
||||||
npm test tests-build/synchronizer.js
|
(cd "$ROOT_DIR" && npm test tests-build/synchronizer.js)
|
@ -15,7 +15,7 @@ process.on('unhandledRejection', (reason, p) => {
|
|||||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 9000; // The first test is slow because the database needs to be built
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000; // The first test is slow because the database needs to be built
|
||||||
|
|
||||||
async function allItems() {
|
async function allItems() {
|
||||||
let folders = await Folder.all();
|
let folders = await Folder.all();
|
||||||
@ -62,598 +62,571 @@ describe('Synchronizer', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('should create remote items', async (done) => {
|
it('should create remote items', async (done) => {
|
||||||
// let folder = await Folder.save({ title: "folder1" });
|
let folder = await Folder.save({ title: "folder1" });
|
||||||
// await Note.save({ title: "un", parent_id: folder.id });
|
await Note.save({ title: "un", parent_id: folder.id });
|
||||||
|
|
||||||
// let all = await allItems();
|
let all = await allItems();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await localItemsSameAsRemote(all, expect);
|
await localItemsSameAsRemote(all, expect);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should update remote item', async (done) => {
|
it('should update remote item', async (done) => {
|
||||||
// let folder = await Folder.save({ title: "folder1" });
|
let folder = await Folder.save({ title: "folder1" });
|
||||||
// let note = await Note.save({ title: "un", parent_id: folder.id });
|
let note = await Note.save({ title: "un", parent_id: folder.id });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await Note.save({ title: "un UPDATE", id: note.id });
|
await Note.save({ title: "un UPDATE", id: note.id });
|
||||||
|
|
||||||
// let all = await allItems();
|
let all = await allItems();
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await localItemsSameAsRemote(all, expect);
|
await localItemsSameAsRemote(all, expect);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should create local items', async (done) => {
|
it('should create local items', async (done) => {
|
||||||
// let folder = await Folder.save({ title: "folder1" });
|
let folder = await Folder.save({ title: "folder1" });
|
||||||
// await Note.save({ title: "un", parent_id: folder.id });
|
await Note.save({ title: "un", parent_id: folder.id });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let all = await allItems();
|
let all = await allItems();
|
||||||
// await localItemsSameAsRemote(all, expect);
|
|
||||||
|
|
||||||
// done();
|
await localItemsSameAsRemote(all, expect);
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should update local items', async (done) => {
|
done();
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
});
|
||||||
// let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(2);
|
it('should update local items', async (done) => {
|
||||||
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
|
let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await switchClient(2);
|
||||||
|
|
||||||
// await sleep(0.1);
|
await synchronizer().start();
|
||||||
|
|
||||||
// let note2 = await Note.load(note1.id);
|
await sleep(0.1);
|
||||||
// note2.title = "Updated on client 2";
|
|
||||||
// await Note.save(note2);
|
|
||||||
// note2 = await Note.load(note2.id);
|
|
||||||
|
|
||||||
// await synchronizer().start();
|
let note2 = await Note.load(note1.id);
|
||||||
|
note2.title = "Updated on client 2";
|
||||||
|
await Note.save(note2);
|
||||||
|
note2 = await Note.load(note2.id);
|
||||||
|
|
||||||
// await switchClient(1);
|
await synchronizer().start();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await switchClient(1);
|
||||||
|
|
||||||
// let all = await allItems();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await localItemsSameAsRemote(all, expect);
|
let all = await allItems();
|
||||||
|
|
||||||
// done();
|
await localItemsSameAsRemote(all, expect);
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should resolve note conflicts', async (done) => {
|
done();
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
});
|
||||||
// let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(2);
|
it('should resolve note conflicts', async (done) => {
|
||||||
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
|
let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await switchClient(2);
|
||||||
// let note2 = await Note.load(note1.id);
|
|
||||||
// note2.title = "Updated on client 2";
|
|
||||||
// await Note.save(note2);
|
|
||||||
// note2 = await Note.load(note2.id);
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(1);
|
await synchronizer().start();
|
||||||
|
let note2 = await Note.load(note1.id);
|
||||||
|
note2.title = "Updated on client 2";
|
||||||
|
await Note.save(note2);
|
||||||
|
note2 = await Note.load(note2.id);
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
// let note2conf = await Note.load(note1.id);
|
await switchClient(1);
|
||||||
// note2conf.title = "Updated on client 1";
|
|
||||||
// await Note.save(note2conf);
|
|
||||||
// note2conf = await Note.load(note1.id);
|
|
||||||
// await synchronizer().start();
|
|
||||||
// let conflictedNotes = await Note.conflictedNotes();
|
|
||||||
// expect(conflictedNotes.length).toBe(1);
|
|
||||||
|
|
||||||
// // Other than the id (since the conflicted note is a duplicate), and the is_conflict property
|
let note2conf = await Note.load(note1.id);
|
||||||
// // the conflicted and original note must be the same in every way, to make sure no data has been lost.
|
note2conf.title = "Updated on client 1";
|
||||||
// let conflictedNote = conflictedNotes[0];
|
await Note.save(note2conf);
|
||||||
// expect(conflictedNote.id == note2conf.id).toBe(false);
|
note2conf = await Note.load(note1.id);
|
||||||
// for (let n in conflictedNote) {
|
await synchronizer().start();
|
||||||
// if (!conflictedNote.hasOwnProperty(n)) continue;
|
let conflictedNotes = await Note.conflictedNotes();
|
||||||
// if (n == 'id' || n == 'is_conflict') continue;
|
expect(conflictedNotes.length).toBe(1);
|
||||||
// expect(conflictedNote[n]).toBe(note2conf[n], 'Property: ' + n);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let noteUpdatedFromRemote = await Note.load(note1.id);
|
// Other than the id (since the conflicted note is a duplicate), and the is_conflict property
|
||||||
// for (let n in noteUpdatedFromRemote) {
|
// the conflicted and original note must be the same in every way, to make sure no data has been lost.
|
||||||
// if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue;
|
let conflictedNote = conflictedNotes[0];
|
||||||
// expect(noteUpdatedFromRemote[n]).toBe(note2[n], 'Property: ' + n);
|
expect(conflictedNote.id == note2conf.id).toBe(false);
|
||||||
// }
|
for (let n in conflictedNote) {
|
||||||
|
if (!conflictedNote.hasOwnProperty(n)) continue;
|
||||||
|
if (n == 'id' || n == 'is_conflict') continue;
|
||||||
|
expect(conflictedNote[n]).toBe(note2conf[n], 'Property: ' + n);
|
||||||
|
}
|
||||||
|
|
||||||
// done();
|
let noteUpdatedFromRemote = await Note.load(note1.id);
|
||||||
// });
|
for (let n in noteUpdatedFromRemote) {
|
||||||
|
if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue;
|
||||||
|
expect(noteUpdatedFromRemote[n]).toBe(note2[n], 'Property: ' + n);
|
||||||
|
}
|
||||||
|
|
||||||
// it('should resolve folders conflicts', async (done) => {
|
done();
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
});
|
||||||
// let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(2); // ----------------------------------
|
it('should resolve folders conflicts', async (done) => {
|
||||||
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
|
let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await switchClient(2); // ----------------------------------
|
||||||
|
|
||||||
// await sleep(0.1);
|
await synchronizer().start();
|
||||||
|
|
||||||
// let folder1_modRemote = await Folder.load(folder1.id);
|
await sleep(0.1);
|
||||||
// folder1_modRemote.title = "folder1 UPDATE CLIENT 2";
|
|
||||||
// await Folder.save(folder1_modRemote);
|
|
||||||
// folder1_modRemote = await Folder.load(folder1_modRemote.id);
|
|
||||||
|
|
||||||
// await synchronizer().start();
|
let folder1_modRemote = await Folder.load(folder1.id);
|
||||||
|
folder1_modRemote.title = "folder1 UPDATE CLIENT 2";
|
||||||
|
await Folder.save(folder1_modRemote);
|
||||||
|
folder1_modRemote = await Folder.load(folder1_modRemote.id);
|
||||||
|
|
||||||
// await switchClient(1); // ----------------------------------
|
await synchronizer().start();
|
||||||
|
|
||||||
// await sleep(0.1);
|
await switchClient(1); // ----------------------------------
|
||||||
|
|
||||||
// let folder1_modLocal = await Folder.load(folder1.id);
|
await sleep(0.1);
|
||||||
// folder1_modLocal.title = "folder1 UPDATE CLIENT 1";
|
|
||||||
// await Folder.save(folder1_modLocal);
|
|
||||||
// folder1_modLocal = await Folder.load(folder1.id);
|
|
||||||
|
|
||||||
// await synchronizer().start();
|
let folder1_modLocal = await Folder.load(folder1.id);
|
||||||
|
folder1_modLocal.title = "folder1 UPDATE CLIENT 1";
|
||||||
|
await Folder.save(folder1_modLocal);
|
||||||
|
folder1_modLocal = await Folder.load(folder1.id);
|
||||||
|
|
||||||
// let folder1_final = await Folder.load(folder1.id);
|
await synchronizer().start();
|
||||||
// expect(folder1_final.title).toBe(folder1_modRemote.title);
|
|
||||||
|
|
||||||
// done();
|
let folder1_final = await Folder.load(folder1.id);
|
||||||
// });
|
expect(folder1_final.title).toBe(folder1_modRemote.title);
|
||||||
|
|
||||||
// it('should delete remote notes', async (done) => {
|
done();
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
});
|
||||||
// let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(2);
|
it('should delete remote notes', async (done) => {
|
||||||
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
|
let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await switchClient(2);
|
||||||
|
|
||||||
// await sleep(0.1);
|
await synchronizer().start();
|
||||||
|
|
||||||
// await Note.delete(note1.id);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await Note.delete(note1.id);
|
||||||
|
|
||||||
// let files = await fileApi().list();
|
await synchronizer().start();
|
||||||
// files = files.items;
|
|
||||||
|
|
||||||
// expect(files.length).toBe(1);
|
let files = await fileApi().list();
|
||||||
// expect(files[0].path).toBe(Folder.systemPath(folder1));
|
files = files.items;
|
||||||
|
|
||||||
// let deletedItems = await BaseItem.deletedItems(syncTargetId());
|
expect(files.length).toBe(1);
|
||||||
// expect(deletedItems.length).toBe(0);
|
expect(files[0].path).toBe(Folder.systemPath(folder1));
|
||||||
|
|
||||||
// done();
|
let deletedItems = await BaseItem.deletedItems(syncTargetId());
|
||||||
// });
|
expect(deletedItems.length).toBe(0);
|
||||||
|
|
||||||
// it('should delete local notes', async (done) => {
|
done();
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
});
|
||||||
// let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(2);
|
it('should delete local notes', async (done) => {
|
||||||
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
|
let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await switchClient(2);
|
||||||
// await Note.delete(note1.id);
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(1);
|
await synchronizer().start();
|
||||||
|
await Note.delete(note1.id);
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
// await synchronizer().start();
|
await switchClient(1);
|
||||||
// let items = await allItems();
|
|
||||||
// expect(items.length).toBe(1);
|
await synchronizer().start();
|
||||||
// let deletedItems = await BaseItem.deletedItems(syncTargetId());
|
let items = await allItems();
|
||||||
// expect(deletedItems.length).toBe(0);
|
expect(items.length).toBe(1);
|
||||||
|
let deletedItems = await BaseItem.deletedItems(syncTargetId());
|
||||||
|
expect(deletedItems.length).toBe(0);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should delete remote folder', async (done) => {
|
it('should delete remote folder', async (done) => {
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
// let folder2 = await Folder.save({ title: "folder2" });
|
let folder2 = await Folder.save({ title: "folder2" });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await Folder.delete(folder2.id);
|
await Folder.delete(folder2.id);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let all = await allItems();
|
let all = await allItems();
|
||||||
// localItemsSameAsRemote(all, expect);
|
localItemsSameAsRemote(all, expect);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should delete local folder', async (done) => {
|
it('should delete local folder', async (done) => {
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
// let folder2 = await Folder.save({ title: "folder2" });
|
let folder2 = await Folder.save({ title: "folder2" });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await Folder.delete(folder2.id);
|
await Folder.delete(folder2.id);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let items = await allItems();
|
let items = await allItems();
|
||||||
// localItemsSameAsRemote(items, expect);
|
localItemsSameAsRemote(items, expect);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', async (done) => {
|
it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', async (done) => {
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// await Folder.delete(folder1.id);
|
await Folder.delete(folder1.id);
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// let note = await Note.save({ title: "note1", parent_id: folder1.id });
|
let note = await Note.save({ title: "note1", parent_id: folder1.id });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// let items = await allItems();
|
let items = await allItems();
|
||||||
// expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
// expect(items[0].title).toBe('note1');
|
expect(items[0].title).toBe('note1');
|
||||||
// expect(items[0].is_conflict).toBe(1);
|
expect(items[0].is_conflict).toBe(1);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should resolve conflict if note has been deleted remotely and locally', async (done) => {
|
it('should resolve conflict if note has been deleted remotely and locally', async (done) => {
|
||||||
// let folder = await Folder.save({ title: "folder" });
|
let folder = await Folder.save({ title: "folder" });
|
||||||
// let note = await Note.save({ title: "note", parent_id: folder.title });
|
let note = await Note.save({ title: "note", parent_id: folder.title });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// await Note.delete(note.id);
|
await Note.delete(note.id);
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// await Note.delete(note.id);
|
await Note.delete(note.id);
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let items = await allItems();
|
let items = await allItems();
|
||||||
// expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
// expect(items[0].title).toBe('folder');
|
expect(items[0].title).toBe('folder');
|
||||||
|
|
||||||
// localItemsSameAsRemote(items, expect);
|
localItemsSameAsRemote(items, expect);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should cross delete all folders', async (done) => {
|
it('should cross delete all folders', async (done) => {
|
||||||
// // If client1 and 2 have two folders, client 1 deletes item 1 and client
|
// If client1 and 2 have two folders, client 1 deletes item 1 and client
|
||||||
// // 2 deletes item 2, they should both end up with no items after sync.
|
// 2 deletes item 2, they should both end up with no items after sync.
|
||||||
|
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
// let folder2 = await Folder.save({ title: "folder2" });
|
let folder2 = await Folder.save({ title: "folder2" });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await Folder.delete(folder1.id);
|
await Folder.delete(folder1.id);
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// await Folder.delete(folder2.id);
|
await Folder.delete(folder2.id);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let items2 = await allItems();
|
let items2 = await allItems();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let items1 = await allItems();
|
let items1 = await allItems();
|
||||||
|
|
||||||
// expect(items1.length).toBe(0);
|
expect(items1.length).toBe(0);
|
||||||
// expect(items1.length).toBe(items2.length);
|
expect(items1.length).toBe(items2.length);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should handle conflict when remote note is deleted then local note is modified', async (done) => {
|
it('should handle conflict when remote note is deleted then local note is modified', async (done) => {
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
// let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await Note.delete(note1.id);
|
await Note.delete(note1.id);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// let newTitle = 'Modified after having been deleted';
|
let newTitle = 'Modified after having been deleted';
|
||||||
// await Note.save({ id: note1.id, title: newTitle });
|
await Note.save({ id: note1.id, title: newTitle });
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let conflictedNotes = await Note.conflictedNotes();
|
let conflictedNotes = await Note.conflictedNotes();
|
||||||
|
|
||||||
// expect(conflictedNotes.length).toBe(1);
|
expect(conflictedNotes.length).toBe(1);
|
||||||
// expect(conflictedNotes[0].title).toBe(newTitle);
|
expect(conflictedNotes[0].title).toBe(newTitle);
|
||||||
|
|
||||||
// let unconflictedNotes = await Note.unconflictedNotes();
|
let unconflictedNotes = await Note.unconflictedNotes();
|
||||||
|
|
||||||
// expect(unconflictedNotes.length).toBe(0);
|
expect(unconflictedNotes.length).toBe(0);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should handle conflict when remote folder is deleted then local folder is renamed', async (done) => {
|
it('should handle conflict when remote folder is deleted then local folder is renamed', async (done) => {
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
// let folder2 = await Folder.save({ title: "folder2" });
|
let folder2 = await Folder.save({ title: "folder2" });
|
||||||
// let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
let note1 = await Note.save({ title: "un", parent_id: folder1.id });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await Folder.delete(folder1.id);
|
await Folder.delete(folder1.id);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// let newTitle = 'Modified after having been deleted';
|
let newTitle = 'Modified after having been deleted';
|
||||||
// await Folder.save({ id: folder1.id, title: newTitle });
|
await Folder.save({ id: folder1.id, title: newTitle });
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let items = await allItems();
|
let items = await allItems();
|
||||||
|
|
||||||
// expect(items.length).toBe(1);
|
expect(items.length).toBe(1);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should allow duplicate folder titles', async (done) => {
|
it('should allow duplicate folder titles', async (done) => {
|
||||||
// let localF1 = await Folder.save({ title: "folder" });
|
let localF1 = await Folder.save({ title: "folder" });
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// let remoteF2 = await Folder.save({ title: "folder" });
|
let remoteF2 = await Folder.save({ title: "folder" });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// let localF2 = await Folder.load(remoteF2.id);
|
let localF2 = await Folder.load(remoteF2.id);
|
||||||
|
|
||||||
// expect(localF2.title == remoteF2.title).toBe(true);
|
expect(localF2.title == remoteF2.title).toBe(true);
|
||||||
|
|
||||||
// // Then that folder that has been renamed locally should be set in such a way
|
// Then that folder that has been renamed locally should be set in such a way
|
||||||
// // that synchronizing it applies the title change remotely, and that new title
|
// that synchronizing it applies the title change remotely, and that new title
|
||||||
// // should be retrieved by client 2.
|
// should be retrieved by client 2.
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
// await sleep(0.1);
|
await sleep(0.1);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// remoteF2 = await Folder.load(remoteF2.id);
|
remoteF2 = await Folder.load(remoteF2.id);
|
||||||
|
|
||||||
// expect(remoteF2.title == localF2.title).toBe(true);
|
expect(remoteF2.title == localF2.title).toBe(true);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should sync tags', async (done) => {
|
it('should sync tags', async (done) => {
|
||||||
// let f1 = await Folder.save({ title: "folder" });
|
let f1 = await Folder.save({ title: "folder" });
|
||||||
// let n1 = await Note.save({ title: "mynote" });
|
let n1 = await Note.save({ title: "mynote" });
|
||||||
// let n2 = await Note.save({ title: "mynote2" });
|
let n2 = await Note.save({ title: "mynote2" });
|
||||||
// let tag = await Tag.save({ title: 'mytag' });
|
let tag = await Tag.save({ title: 'mytag' });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// let remoteTag = await Tag.loadByTitle(tag.title);
|
let remoteTag = await Tag.loadByTitle(tag.title);
|
||||||
// expect(!!remoteTag).toBe(true);
|
expect(!!remoteTag).toBe(true);
|
||||||
// expect(remoteTag.id).toBe(tag.id);
|
expect(remoteTag.id).toBe(tag.id);
|
||||||
// await Tag.addNote(remoteTag.id, n1.id);
|
await Tag.addNote(remoteTag.id, n1.id);
|
||||||
// await Tag.addNote(remoteTag.id, n2.id);
|
await Tag.addNote(remoteTag.id, n2.id);
|
||||||
// let noteIds = await Tag.noteIds(tag.id);
|
let noteIds = await Tag.noteIds(tag.id);
|
||||||
// expect(noteIds.length).toBe(2);
|
expect(noteIds.length).toBe(2);
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(1);
|
await switchClient(1);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// let remoteNoteIds = await Tag.noteIds(tag.id);
|
let remoteNoteIds = await Tag.noteIds(tag.id);
|
||||||
// expect(remoteNoteIds.length).toBe(2);
|
expect(remoteNoteIds.length).toBe(2);
|
||||||
// await Tag.removeNote(tag.id, n1.id);
|
await Tag.removeNote(tag.id, n1.id);
|
||||||
// remoteNoteIds = await Tag.noteIds(tag.id);
|
remoteNoteIds = await Tag.noteIds(tag.id);
|
||||||
// expect(remoteNoteIds.length).toBe(1);
|
expect(remoteNoteIds.length).toBe(1);
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// noteIds = await Tag.noteIds(tag.id);
|
noteIds = await Tag.noteIds(tag.id);
|
||||||
// expect(noteIds.length).toBe(1);
|
expect(noteIds.length).toBe(1);
|
||||||
// expect(remoteNoteIds[0]).toBe(noteIds[0]);
|
expect(remoteNoteIds[0]).toBe(noteIds[0]);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should not sync notes with conflicts', async (done) => {
|
it('should not sync notes with conflicts', async (done) => {
|
||||||
// let f1 = await Folder.save({ title: "folder" });
|
let f1 = await Folder.save({ title: "folder" });
|
||||||
// let n1 = await Note.save({ title: "mynote", parent_id: f1.id, is_conflict: 1 });
|
let n1 = await Note.save({ title: "mynote", parent_id: f1.id, is_conflict: 1 });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// let notes = await Note.all();
|
let notes = await Note.all();
|
||||||
// let folders = await Folder.all()
|
let folders = await Folder.all()
|
||||||
// expect(notes.length).toBe(0);
|
expect(notes.length).toBe(0);
|
||||||
// expect(folders.length).toBe(1);
|
expect(folders.length).toBe(1);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should not try to delete on remote conflicted notes that have been deleted', async (done) => {
|
it('should not try to delete on remote conflicted notes that have been deleted', async (done) => {
|
||||||
// let f1 = await Folder.save({ title: "folder" });
|
let f1 = await Folder.save({ title: "folder" });
|
||||||
// let n1 = await Note.save({ title: "mynote", parent_id: f1.id });
|
let n1 = await Note.save({ title: "mynote", parent_id: f1.id });
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
// await switchClient(2);
|
await switchClient(2);
|
||||||
|
|
||||||
// await synchronizer().start();
|
await synchronizer().start();
|
||||||
// await Note.save({ id: n1.id, is_conflict: 1 });
|
await Note.save({ id: n1.id, is_conflict: 1 });
|
||||||
// await Note.delete(n1.id);
|
await Note.delete(n1.id);
|
||||||
// const deletedItems = await BaseItem.deletedItems(syncTargetId());
|
const deletedItems = await BaseItem.deletedItems(syncTargetId());
|
||||||
|
|
||||||
// expect(deletedItems.length).toBe(0);
|
expect(deletedItems.length).toBe(0);
|
||||||
|
|
||||||
// done();
|
done();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// it('should not consider it is a conflict if neither the title nor body of the note have changed', async (done) => {
|
it('should not consider it is a conflict if neither the title nor body of the note have changed', async (done) => {
|
||||||
// // That was previously a common conflict:
|
// That was previously a common conflict:
|
||||||
// // - Client 1 mark todo as "done", and sync
|
// - Client 1 mark todo as "done", and sync
|
||||||
// // - Client 2 doesn't sync, mark todo as "done" todo. Then sync.
|
// - Client 2 doesn't sync, mark todo as "done" todo. Then sync.
|
||||||
// // In theory it is a conflict because the todo_completed dates are different
|
// In theory it is a conflict because the todo_completed dates are different
|
||||||
// // but in practice it doesn't matter, we can just take the date when the
|
// but in practice it doesn't matter, we can just take the date when the
|
||||||
// // todo was marked as "done" the first time.
|
// todo was marked as "done" the first time.
|
||||||
|
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
|
||||||
// let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id });
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(2);
|
|
||||||
|
|
||||||
// await synchronizer().start();
|
|
||||||
// let note2 = await Note.load(note1.id);
|
|
||||||
// note2.todo_completed = time.unixMs()-1;
|
|
||||||
// await Note.save(note2);
|
|
||||||
// note2 = await Note.load(note2.id);
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(1);
|
|
||||||
|
|
||||||
// let note2conf = await Note.load(note1.id);
|
|
||||||
// note2conf.todo_completed = time.unixMs();
|
|
||||||
// await Note.save(note2conf);
|
|
||||||
// note2conf = await Note.load(note1.id);
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// let conflictedNotes = await Note.conflictedNotes();
|
|
||||||
// expect(conflictedNotes.length).toBe(0);
|
|
||||||
|
|
||||||
// let notes = await Note.all();
|
|
||||||
// expect(notes.length).toBe(1);
|
|
||||||
// expect(notes[0].id).toBe(note1.id);
|
|
||||||
// expect(notes[0].todo_completed).toBe(note2.todo_completed);
|
|
||||||
|
|
||||||
// done();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('items should be downloaded again when user cancels in the middle of delta operation', async (done) => {
|
|
||||||
// let folder1 = await Folder.save({ title: "folder1" });
|
|
||||||
// let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id });
|
|
||||||
// await synchronizer().start();
|
|
||||||
|
|
||||||
// await switchClient(2);
|
|
||||||
|
|
||||||
// synchronizer().debugFlags_ = ['cancelDeltaLoop2'];
|
|
||||||
// let context = await synchronizer().start();
|
|
||||||
// let notes = await Note.all();
|
|
||||||
// expect(notes.length).toBe(0);
|
|
||||||
|
|
||||||
// synchronizer().debugFlags_ = [];
|
|
||||||
// await synchronizer().start({ context: context });
|
|
||||||
// notes = await Note.all();
|
|
||||||
// expect(notes.length).toBe(1);
|
|
||||||
|
|
||||||
// done();
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('should result in the same state if items are synchronised twice with no changes in between', async (done) => {
|
|
||||||
let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id });
|
let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id });
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
await Note.save({id: note1.id, body: "changed", type_: note1.type_ });
|
await switchClient(2);
|
||||||
note1 = await Note.load(note1.id);
|
|
||||||
|
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
let note2 = await Note.load(note1.id);
|
||||||
await Note.save({id: note1.id, body: "changed 2", type_: note1.type_ });
|
note2.todo_completed = time.unixMs()-1;
|
||||||
note1 = await Note.load(note1.id);
|
await Note.save(note2);
|
||||||
|
note2 = await Note.load(note2.id);
|
||||||
await synchronizer().start();
|
await synchronizer().start();
|
||||||
|
|
||||||
let noteNew1 = await Note.load(note1.id);
|
await switchClient(1);
|
||||||
|
|
||||||
//console.info(noteNew1);
|
let note2conf = await Note.load(note1.id);
|
||||||
|
note2conf.todo_completed = time.unixMs();
|
||||||
|
await Note.save(note2conf);
|
||||||
|
note2conf = await Note.load(note1.id);
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
let conflictedNotes = await Note.conflictedNotes();
|
let conflictedNotes = await Note.conflictedNotes();
|
||||||
expect(conflictedNotes.length).toBe(0);
|
expect(conflictedNotes.length).toBe(0);
|
||||||
|
|
||||||
expect(BaseModel.modelsAreSame(note1, noteNew1)).toBe(true);
|
let notes = await Note.all();
|
||||||
|
expect(notes.length).toBe(1);
|
||||||
|
expect(notes[0].id).toBe(note1.id);
|
||||||
|
expect(notes[0].todo_completed).toBe(note2.todo_completed);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('items should be downloaded again when user cancels in the middle of delta operation', async (done) => {
|
||||||
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
|
let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id });
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
|
await switchClient(2);
|
||||||
|
|
||||||
|
synchronizer().debugFlags_ = ['cancelDeltaLoop2'];
|
||||||
|
let context = await synchronizer().start();
|
||||||
|
let notes = await Note.all();
|
||||||
|
expect(notes.length).toBe(0);
|
||||||
|
|
||||||
|
synchronizer().debugFlags_ = [];
|
||||||
|
await synchronizer().start({ context: context });
|
||||||
|
notes = await Note.all();
|
||||||
|
expect(notes.length).toBe(1);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -3,4 +3,4 @@ ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
./build.sh || exit 1
|
./build.sh || exit 1
|
||||||
cd "$ROOT_DIR/app"
|
cd "$ROOT_DIR/app"
|
||||||
./node_modules/.bin/electron . --env dev --log-level debug --open-dev-tools "$@"
|
./node_modules/.bin/electron . --env dev --log-level warn --open-dev-tools "$@"
|
18
Tools/android-release-post-process.js
Normal file
18
Tools/android-release-post-process.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const fs = require('fs-extra');
|
||||||
|
const toolUtils = require('./tool-utils.js');
|
||||||
|
|
||||||
|
const rnDir = __dirname + '/../ReactNativeClient';
|
||||||
|
|
||||||
|
function androidVersionNumber() {
|
||||||
|
let content = fs.readFileSync(rnDir + '/android/app/build.gradle', 'utf8');
|
||||||
|
const r = content.match(/versionName\s+"(\d+?\.\d+?\.\d+)"/)
|
||||||
|
if (r.length !== 2) throw new Error('Could not get version number');
|
||||||
|
return r[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// const
|
||||||
|
|
||||||
|
// '/android/app/build/outputs/apk/app-armeabi-v7a-release.apk'
|
||||||
|
|
||||||
|
|
||||||
|
console.info(androidVersionNumber());
|
@ -15,25 +15,7 @@ const cliLocalesDir = cliDir + '/locales';
|
|||||||
const rnDir = rootDir + '/ReactNativeClient';
|
const rnDir = rootDir + '/ReactNativeClient';
|
||||||
const electronDir = rootDir + '/ElectronClient/app';
|
const electronDir = rootDir + '/ElectronClient/app';
|
||||||
|
|
||||||
function execCommand(command) {
|
const { execCommand } = require('./tool-utils.js');
|
||||||
if (!silentLog) console.info('Running: ' + command);
|
|
||||||
|
|
||||||
const exec = require('child_process').exec
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let childProcess = exec(command, (error, stdout, stderr) => {
|
|
||||||
if (error) {
|
|
||||||
if (error.signal == 'SIGTERM') {
|
|
||||||
resolve('Process was killed');
|
|
||||||
} else {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resolve(stdout.trim());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parsePoFile(filePath) {
|
function parsePoFile(filePath) {
|
||||||
const content = fs.readFileSync(filePath);
|
const content = fs.readFileSync(filePath);
|
||||||
|
14
Tools/package-lock.json
generated
14
Tools/package-lock.json
generated
@ -41,6 +41,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
||||||
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
|
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
|
||||||
},
|
},
|
||||||
|
"is-stream": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||||
|
},
|
||||||
"jsonfile": {
|
"jsonfile": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||||
@ -59,6 +64,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz",
|
||||||
"integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA="
|
"integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA="
|
||||||
},
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
|
||||||
|
"requires": {
|
||||||
|
"encoding": "0.1.12",
|
||||||
|
"is-stream": "1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"fs-extra": "^4.0.2",
|
"fs-extra": "^4.0.2",
|
||||||
"gettext-parser": "^1.3.0",
|
"gettext-parser": "^1.3.0",
|
||||||
"marked": "^0.3.7",
|
"marked": "^0.3.7",
|
||||||
"mustache": "^2.3.0"
|
"mustache": "^2.3.0",
|
||||||
|
"node-fetch": "^1.7.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
84
Tools/tool-utils.js
Normal file
84
Tools/tool-utils.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
const toolUtils = {};
|
||||||
|
|
||||||
|
toolUtils.execCommand = function(command) {
|
||||||
|
const exec = require('child_process').exec
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let childProcess = exec(command, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
if (error.signal == 'SIGTERM') {
|
||||||
|
resolve('Process was killed');
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve(stdout.trim());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toolUtils.downloadFile = function(url, targetPath) {
|
||||||
|
const https = require('https');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const file = fs.createWriteStream(targetPath);
|
||||||
|
const request = https.get(url, function(response) {
|
||||||
|
if (response.statusCode !== 200) reject(new Error('HTTP error ' + response.statusCode));
|
||||||
|
response.pipe(file);
|
||||||
|
file.on('finish', function() {
|
||||||
|
file.close();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}).on('error', (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toolUtils.fileSha256 = function(filePath) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const fs = require('fs');
|
||||||
|
const algo = 'sha256';
|
||||||
|
const shasum = crypto.createHash(algo);
|
||||||
|
|
||||||
|
const s = fs.ReadStream(filePath);
|
||||||
|
s.on('data', function(d) { shasum.update(d); });
|
||||||
|
s.on('end', function() {
|
||||||
|
const d = shasum.digest('hex');
|
||||||
|
resolve(d);
|
||||||
|
});
|
||||||
|
s.on('error', function(error) {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toolUtils.unlinkForce = async function(filePath) {
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.unlink(filePath);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === 'ENOENT') return;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toolUtils.fileExists = async function(filePath) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fs.stat(filePath, function(err, stat) {
|
||||||
|
if (err == null) {
|
||||||
|
resolve(true);
|
||||||
|
} else if(err.code == 'ENOENT') {
|
||||||
|
resolve(false);
|
||||||
|
} else {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = toolUtils;
|
27
Tools/update-homebrew.js
Normal file
27
Tools/update-homebrew.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
"use strict"
|
||||||
|
|
||||||
|
// https://github.com/Homebrew/homebrew-core/blob/master/CONTRIBUTING.md
|
||||||
|
|
||||||
|
const rootDir = __dirname + '/..';
|
||||||
|
const { execCommand, downloadFile, fileSha256, unlinkForce } = require('./tool-utils.js');
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const url = await execCommand('npm view joplin dist.tarball');
|
||||||
|
const targetPath = rootDir + '/latest-cli.tar.gz';
|
||||||
|
await unlinkForce(targetPath);
|
||||||
|
await downloadFile(url, targetPath);
|
||||||
|
const sha256 = await fileSha256(targetPath);
|
||||||
|
await unlinkForce(targetPath);
|
||||||
|
|
||||||
|
console.info('URL = ' + url);
|
||||||
|
console.info('SHA256 = ' + sha256);
|
||||||
|
console.info('');
|
||||||
|
console.info('brew bump-formula-pr --strict joplin --url=' + url + ' --sha256=' + sha256);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error) => {
|
||||||
|
console.error('Fatal error');
|
||||||
|
console.error(error);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user