Avoid conflicts when synced content matches

This commit is contained in:
shi.changliang 2026-06-09 11:00:17 +08:00
parent c64b774607
commit dc1fac3f80
5 changed files with 43 additions and 3 deletions

View file

@ -1,7 +1,7 @@
{
"id": "obsync",
"name": "S3 Vault Sync",
"version": "0.1.1",
"version": "0.1.2",
"minAppVersion": "1.6.6",
"description": "Sync vault files through OSS / S3-compatible object storage.",
"author": "Chaly",

View file

@ -1,6 +1,6 @@
{
"name": "obsync",
"version": "0.1.1",
"version": "0.1.2",
"description": "Plugin for OSS / S3-compatible vault sync.",
"main": "main.js",
"scripts": {

View file

@ -589,6 +589,41 @@ describe("sync engine", () => {
expect(store.manifest.paths["notes/today.md"]?.contentHash).toBe(await hashText("local"));
});
test("does not create a conflict when local and remote content match", async () => {
const baseHash = await hashText("base");
const sameHash = await hashText("same");
const vault = new FakeVault({ "notes/today.md": "same" });
const store = new FakeObjectStore();
const state: LocalSyncState = {
files: {
"notes/today.md": {
lastSyncedHash: baseHash,
remoteHash: baseHash,
deleted: false,
version: "ver_base",
},
},
};
await store.putText(blobObjectKey(sameHash), "same");
store.manifest.paths["notes/today.md"] = {
contentHash: sameHash,
size: 4,
updatedAt: 2000,
updatedBy: "dev_other",
revision: 2,
version: "ver_remote",
};
const result = await sync(vault, store, state, 3000);
expect(result.conflicts).toBe(0);
expect(result.downloaded).toBe(1);
expect(await vault.readText("notes/today.md")).toBe("same");
expect(await vault.readText("notes/today.conflict.Mac.19700101-000003.md")).toBe("");
expect(state.files["notes/today.md"]?.lastSyncedHash).toBe(sameHash);
expect(state.files["notes/today.md"]?.version).toBe("ver_remote");
});
test("releaseDeletedContent removes deleted tombstones and unreferenced blobs", async () => {
const keptHash = await hashText("kept");
const deletedHash = await hashText("deleted");

View file

@ -504,6 +504,10 @@ function planPathAction(input: {
const localChanged = !input.previous || input.previous.deleted || input.local.hash !== input.previous.lastSyncedHash;
const remoteChanged = input.remote.version !== input.previous?.version || input.remote.contentHash !== input.previous?.remoteHash;
if (input.local.hash === input.remote.contentHash) {
return remoteChanged ? "download" : "noop";
}
if (!localChanged && !remoteChanged) {
return "noop";
}

View file

@ -1,3 +1,4 @@
{
"0.1.1": "1.6.6"
"0.1.1": "1.6.6",
"0.1.2": "1.6.6"
}