mirror of
https://github.com/remotely-save/remotely-save.git
synced 2024-06-07 21:10:45 +00:00
better sync operations for folders
This commit is contained in:
parent
94c7a4a874
commit
3dfe215103
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"id": "remotely-save",
|
"id": "remotely-save",
|
||||||
"name": "Remotely Save",
|
"name": "Remotely Save",
|
||||||
"version": "0.3.2",
|
"version": "0.3.3",
|
||||||
"minAppVersion": "0.12.15",
|
"minAppVersion": "0.13.21",
|
||||||
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
||||||
"author": "fyears",
|
"author": "fyears",
|
||||||
"authorUrl": "https://github.com/fyears",
|
"authorUrl": "https://github.com/fyears",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "remotely-save",
|
"name": "remotely-save",
|
||||||
"version": "0.3.2",
|
"version": "0.3.3",
|
||||||
"description": "This is yet another sync plugin for Obsidian app.",
|
"description": "This is yet another sync plugin for Obsidian app.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev2": "node esbuild.config.mjs",
|
"dev2": "node esbuild.config.mjs",
|
||||||
@ -70,7 +70,7 @@
|
|||||||
"loglevel": "^1.8.0",
|
"loglevel": "^1.8.0",
|
||||||
"mime-types": "^2.1.33",
|
"mime-types": "^2.1.33",
|
||||||
"nanoid": "^3.1.30",
|
"nanoid": "^3.1.30",
|
||||||
"obsidian": "^0.12.0",
|
"obsidian": "^0.13.26",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"qrcode": "^1.5.0",
|
"qrcode": "^1.5.0",
|
||||||
|
@ -113,3 +113,5 @@ export interface FileOrFolderMixedState {
|
|||||||
syncDone?: "done";
|
syncDone?: "done";
|
||||||
remoteEncryptedKey?: string;
|
remoteEncryptedKey?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const API_VER_STAT_FOLDER = "0.13.27";
|
||||||
|
@ -199,6 +199,7 @@ export default class RemotelySavePlugin extends Plugin {
|
|||||||
origMetadataOnRemote.deletions,
|
origMetadataOnRemote.deletions,
|
||||||
localHistory,
|
localHistory,
|
||||||
client.serviceType,
|
client.serviceType,
|
||||||
|
this.app.vault,
|
||||||
this.settings.password
|
this.settings.password
|
||||||
);
|
);
|
||||||
log.info(plan.mixedStates); // for debugging
|
log.info(plan.mixedStates); // for debugging
|
||||||
|
53
src/sync.ts
53
src/sync.ts
@ -1,9 +1,16 @@
|
|||||||
import { TAbstractFile, TFile, TFolder, Vault } from "obsidian";
|
import {
|
||||||
import type {
|
TAbstractFile,
|
||||||
|
TFile,
|
||||||
|
TFolder,
|
||||||
|
Vault,
|
||||||
|
requireApiVersion,
|
||||||
|
} from "obsidian";
|
||||||
|
import {
|
||||||
RemoteItem,
|
RemoteItem,
|
||||||
SUPPORTED_SERVICES_TYPE,
|
SUPPORTED_SERVICES_TYPE,
|
||||||
DecisionType,
|
DecisionType,
|
||||||
FileOrFolderMixedState,
|
FileOrFolderMixedState,
|
||||||
|
API_VER_STAT_FOLDER,
|
||||||
} from "./baseTypes";
|
} from "./baseTypes";
|
||||||
import {
|
import {
|
||||||
decryptBase32ToString,
|
decryptBase32ToString,
|
||||||
@ -505,9 +512,10 @@ const assignOperationToFileInplace = (
|
|||||||
throw Error(`no decision for ${JSON.stringify(r)}`);
|
throw Error(`no decision for ${JSON.stringify(r)}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const assignOperationToFolderInplace = (
|
const assignOperationToFolderInplace = async (
|
||||||
origRecord: FileOrFolderMixedState,
|
origRecord: FileOrFolderMixedState,
|
||||||
keptFolder: Set<string>,
|
keptFolder: Set<string>,
|
||||||
|
vault: Vault,
|
||||||
password: string = ""
|
password: string = ""
|
||||||
) => {
|
) => {
|
||||||
let r = origRecord;
|
let r = origRecord;
|
||||||
@ -523,10 +531,42 @@ const assignOperationToFolderInplace = (
|
|||||||
|
|
||||||
if (r.deltimeLocal !== undefined || r.deltimeRemote !== undefined) {
|
if (r.deltimeLocal !== undefined || r.deltimeRemote !== undefined) {
|
||||||
// it has some deletion "commands"
|
// it has some deletion "commands"
|
||||||
|
|
||||||
|
const deltimeLocal = r.deltimeLocal !== undefined ? r.deltimeLocal : -1;
|
||||||
|
const deltimeRemote =
|
||||||
|
r.deltimeRemote !== undefined ? r.deltimeRemote : -1;
|
||||||
|
|
||||||
|
// if it was created after deletion, we should keep it as is
|
||||||
|
if (requireApiVersion(API_VER_STAT_FOLDER)) {
|
||||||
|
if (r.existLocal) {
|
||||||
|
try {
|
||||||
|
const { ctime, mtime } = await vault.adapter.stat(r.key);
|
||||||
|
const cmtime = Math.max(ctime, mtime);
|
||||||
if (
|
if (
|
||||||
r.deltimeLocal !== undefined &&
|
cmtime > 0 &&
|
||||||
r.deltimeLocal >= (r.deltimeRemote !== undefined ? r.deltimeRemote : -1)
|
cmtime >= deltimeLocal &&
|
||||||
|
cmtime >= deltimeRemote
|
||||||
) {
|
) {
|
||||||
|
keptFolder.add(getParentFolder(r.key));
|
||||||
|
if (r.existLocal && r.existRemote) {
|
||||||
|
r.decision = "skipFolder";
|
||||||
|
r.decisionBranch = 14;
|
||||||
|
} else if (r.existLocal || r.existRemote) {
|
||||||
|
r.decision = "createFolder";
|
||||||
|
r.decisionBranch = 15;
|
||||||
|
} else {
|
||||||
|
throw Error(
|
||||||
|
`Error: Folder ${r.key} doesn't exist locally and remotely but is marked must be kept. Abort.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deltimeLocal > 0 && deltimeLocal > deltimeRemote) {
|
||||||
r.decision = "uploadLocalDelHistToRemoteFolder";
|
r.decision = "uploadLocalDelHistToRemoteFolder";
|
||||||
r.decisionBranch = 8;
|
r.decisionBranch = 8;
|
||||||
} else {
|
} else {
|
||||||
@ -585,6 +625,7 @@ export const getSyncPlan = async (
|
|||||||
remoteDeleteHistory: DeletionOnRemote[],
|
remoteDeleteHistory: DeletionOnRemote[],
|
||||||
localDeleteHistory: FileFolderHistoryRecord[],
|
localDeleteHistory: FileFolderHistoryRecord[],
|
||||||
remoteType: SUPPORTED_SERVICES_TYPE,
|
remoteType: SUPPORTED_SERVICES_TYPE,
|
||||||
|
vault: Vault,
|
||||||
password: string = ""
|
password: string = ""
|
||||||
) => {
|
) => {
|
||||||
const mixedStates = await ensembleMixedStates(
|
const mixedStates = await ensembleMixedStates(
|
||||||
@ -609,7 +650,7 @@ export const getSyncPlan = async (
|
|||||||
// decide some folders
|
// decide some folders
|
||||||
// because the keys are sorted by length
|
// because the keys are sorted by length
|
||||||
// so all the children must have been shown up before in the iteration
|
// so all the children must have been shown up before in the iteration
|
||||||
assignOperationToFolderInplace(val, keptFolder, password);
|
await assignOperationToFolderInplace(val, keptFolder, vault, password);
|
||||||
} else {
|
} else {
|
||||||
// get all operations of files
|
// get all operations of files
|
||||||
// and at the same time get some helper info for folders
|
// and at the same time get some helper info for folders
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"0.3.2": "0.12.15"
|
"0.3.2": "0.12.15",
|
||||||
|
"0.3.3": "0.13.21"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user