Compare commits

..
5 Commits
Author SHA1 Message Date
fyears 40d2ee95b7 0.0.10 2021-11-07 15:01:12 +08:00
fyears 5632e28331 make decision works 2021-11-07 15:00:22 +08:00
fyears 2b53a1bf5e to 0.0.9 2021-11-07 14:54:25 +08:00
fyears ccd9e3116c add cross-env 2021-11-07 14:51:00 +08:00
fyears e8d6a50793 update algo 2021-11-07 14:24:24 +08:00
5 changed files with 42 additions and 25 deletions
+13 -13
View File
@@ -14,16 +14,16 @@ Assuming all sources are reliable.
We list all combinations mutually exclusive and collectively exhaustive. We list all combinations mutually exclusive and collectively exhaustive.
| ID | Remote Files | Local files | Local delete rename history | Extra | Decision | | ID | Remote Files | Local files | Local delete rename history | Extra | Decision |
| --- | ------------ | ----------- | --------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | ---- | ------------ | ----------- | --------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 1 | exist | exist | ignore | mtime_remote > mtime_local | download remote file, create local folder if not exists, clear local history if exists | | 1 | exist | exist | ignore | mtime_remote > mtime_local | download remote file, create local folder if not exists, clear local history if exists |
| 2 | exist | exist | ignore | mtime_remote < mtime_local | upload local file, create remote folder if not exists, clear local history if exists | | 2 | exist | exist | ignore | mtime_remote < mtime_local | upload local file, create remote folder if not exists, clear local history if exists |
| 3 | exist | exist | ignore | mtime_remote === mtime_local && size_remote === size_local | clear local history if exists (the file was synced and no changes after last sync) | | 3 | exist | exist | ignore | mtime_remote === mtime_local && password === "" && size_remote === size_local | clear local history if exists (the file was synced and no changes after last sync) |
| 4 | exist | exist | ignore | mtime_remote === mtime_local && size_remote !== size_local | upload local file, clear local history if exists (we always prefer local to remote) | | 4 | exist | exist | ignore | mtime_remote === mtime_local && password === "" && size_remote !== size_local | upload local file, clear local history if exists (we always prefer local to remote) |
| 5 | exist | exist | ignore | If local is a folder. mtime_local === undefined | clear local history if exists. TODO: what if a folder and a previous file share the same name? | | 5 | exist | exist | ignore | mtime_remote === mtime_local && password !== "" | clear local history if exists (in encryption mode, file sizes are unequal. we can only rely on mtime(s)) |
| 6 | exist | not exist | exist | mtime_remote >= delete_time_local | download remote file, create folder if not exists | | 6 | exist | exist | ignore | If local is a folder. mtime_local === undefined | clear local history if exists. TODO: what if a folder and a previous file share the same name? |
| 7 | exist | not exist | exist | mtime_remote < delete_time_local | delete remote file, clear local history | | 7 | exist | not exist | exist | mtime_remote >= delete_time_local | download remote file, create folder if not exists |
| 8 | exist | not exist | not exist | | download remote file, create folder if not exists | | 8 | exist | not exist | exist | mtime_remote < delete_time_local | delete remote file, clear local history |
| 9 | not exist | exist | ignore | If local is a single file. | upload local file, create remote folder if not exists, clear local history if exists | | 9 | exist | not exist | not exist | | download remote file, create folder if not exists |
| 10 | not exist | exist | ignore | If local is a folder. | upload local files recursively, create remote folder if not exists, clear local history if exists | | 10 | not exist | exist | ignore | local may be folder or file | upload local files recursively, create remote folder if not exists, clear local history if exists |
| 11 | not exist | not exist | ignore | | clear local history if exists | | 11 | not exist | not exist | ignore | | clear local history if exists |
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "obsdian-save-remote", "id": "obsdian-save-remote",
"name": "Save remote", "name": "Save remote",
"version": "0.0.8", "version": "0.0.10",
"minAppVersion": "0.12.15", "minAppVersion": "0.12.15",
"description": "This is yet another plugin allowing users to sync notes between local device and the cloud.", "description": "This is yet another plugin allowing users to sync notes between local device and the cloud.",
"author": "fyears", "author": "fyears",
+3 -2
View File
@@ -1,13 +1,13 @@
{ {
"name": "obsidian-save-remote", "name": "obsidian-save-remote",
"version": "0.0.8", "version": "0.0.10",
"description": "This is yet another sync plugin for Obsidian app.", "description": "This is yet another sync plugin for Obsidian app.",
"scripts": { "scripts": {
"dev": "webpack --mode development --watch", "dev": "webpack --mode development --watch",
"build": "webpack --mode production", "build": "webpack --mode production",
"format": "npx prettier --write .", "format": "npx prettier --write .",
"clean": "npx rimraf main.js", "clean": "npx rimraf main.js",
"test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register 'tests/**/*.ts'" "test": "cross-env TS_NODE_COMPILER_OPTIONS={\\\"module\\\":\\\"commonjs\\\"} mocha -r ts-node/register 'tests/**/*.ts'"
}, },
"source": "main.ts", "source": "main.ts",
"keywords": [], "keywords": [],
@@ -19,6 +19,7 @@
"@types/mocha": "^9.0.0", "@types/mocha": "^9.0.0",
"@types/node": "^14.14.37", "@types/node": "^14.14.37",
"chai": "^4.3.4", "chai": "^4.3.4",
"cross-env": "^7.0.3",
"mocha": "^9.1.3", "mocha": "^9.1.3",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"terser-webpack-plugin": "^5.2.4", "terser-webpack-plugin": "^5.2.4",
+24 -8
View File
@@ -190,7 +190,8 @@ const ensembleMixedStates = async (
const getOperation = ( const getOperation = (
origRecord: FileOrFolderMixedState, origRecord: FileOrFolderMixedState,
inplace: boolean = false inplace: boolean = false,
password: string = ""
) => { ) => {
let r = origRecord; let r = origRecord;
if (!inplace) { if (!inplace) {
@@ -238,6 +239,7 @@ const getOperation = (
r.mtime_remote !== undefined && r.mtime_remote !== undefined &&
r.mtime_local !== undefined && r.mtime_local !== undefined &&
r.mtime_remote === r.mtime_local && r.mtime_remote === r.mtime_local &&
password === "" &&
r.size_local === r.size_remote r.size_local === r.size_remote
) { ) {
r.decision = "skip"; r.decision = "skip";
@@ -248,17 +250,31 @@ const getOperation = (
r.mtime_remote !== undefined && r.mtime_remote !== undefined &&
r.mtime_local !== undefined && r.mtime_local !== undefined &&
r.mtime_remote === r.mtime_local && r.mtime_remote === r.mtime_local &&
password === "" &&
r.size_local !== r.size_remote r.size_local !== r.size_remote
) { ) {
r.decision = "upload_clearhist"; r.decision = "upload_clearhist";
r.decision_branch = 4; r.decision_branch = 4;
} else if (
r.exist_remote &&
r.exist_local &&
r.mtime_remote !== undefined &&
r.mtime_local !== undefined &&
r.mtime_remote === r.mtime_local &&
password !== ""
) {
// if we have encryption,
// the size is always unequal
// only mtime(s) are reliable
r.decision = "skip";
r.decision_branch = 5;
} else if (r.exist_remote && r.exist_local && r.mtime_local === undefined) { } else if (r.exist_remote && r.exist_local && r.mtime_local === undefined) {
// this must be a folder! // this must be a folder!
if (!r.key.endsWith("/")) { if (!r.key.endsWith("/")) {
throw Error(`${r.key} is not a folder but lacks local mtime`); throw Error(`${r.key} is not a folder but lacks local mtime`);
} }
r.decision = "skip"; r.decision = "skip";
r.decision_branch = 5; r.decision_branch = 6;
} else if ( } else if (
r.exist_remote && r.exist_remote &&
!r.exist_local && !r.exist_local &&
@@ -268,7 +284,7 @@ const getOperation = (
r.mtime_remote >= r.delete_time_local r.mtime_remote >= r.delete_time_local
) { ) {
r.decision = "download_clearhist"; r.decision = "download_clearhist";
r.decision_branch = 6; r.decision_branch = 7;
} else if ( } else if (
r.exist_remote && r.exist_remote &&
!r.exist_local && !r.exist_local &&
@@ -278,7 +294,7 @@ const getOperation = (
r.mtime_remote < r.delete_time_local r.mtime_remote < r.delete_time_local
) { ) {
r.decision = "delremote_clearhist"; r.decision = "delremote_clearhist";
r.decision_branch = 7; r.decision_branch = 8;
} else if ( } else if (
r.exist_remote && r.exist_remote &&
!r.exist_local && !r.exist_local &&
@@ -287,10 +303,10 @@ const getOperation = (
r.delete_time_local == undefined r.delete_time_local == undefined
) { ) {
r.decision = "download"; r.decision = "download";
r.decision_branch = 8; r.decision_branch = 9;
} else if (!r.exist_remote && r.exist_local && r.mtime_remote === undefined) { } else if (!r.exist_remote && r.exist_local && r.mtime_remote === undefined) {
r.decision = "upload_clearhist"; r.decision = "upload_clearhist";
r.decision_branch = 9; r.decision_branch = 10;
} else if ( } else if (
!r.exist_remote && !r.exist_remote &&
!r.exist_local && !r.exist_local &&
@@ -298,7 +314,7 @@ const getOperation = (
r.mtime_local === undefined r.mtime_local === undefined
) { ) {
r.decision = "clearhist"; r.decision = "clearhist";
r.decision_branch = 10; r.decision_branch = 11;
} }
return r; return r;
@@ -319,7 +335,7 @@ export const getSyncPlan = async (
password password
); );
for (const [key, val] of Object.entries(mixedStates)) { for (const [key, val] of Object.entries(mixedStates)) {
getOperation(val, true); getOperation(val, true, password);
} }
const plan = { const plan = {
ts: Date.now(), ts: Date.now(),
+1 -1
View File
@@ -1,3 +1,3 @@
{ {
"0.0.8": "0.12.15" "0.0.10": "0.12.15"
} }