From 07dca55fe1652f425eb4d81af52c79ec85d77445 Mon Sep 17 00:00:00 2001 From: TheOutdoorProgrammer Date: Fri, 30 Jan 2026 12:05:55 -0500 Subject: [PATCH] Fix: Detect files modified directly on GitHub Fixes #45 - Plugin now detects when files are edited via GitHub web UI. The manifest only updates when syncing through this plugin. We now compare actual tree SHAs with manifest SHAs to catch external modifications. Changes: - Compare remote file SHAs from git tree with manifest SHAs - Update manifest when external changes detected - Handle new files added externally --- src/sync-manager.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/sync-manager.ts b/src/sync-manager.ts index da11a5a..6c52756 100644 --- a/src/sync-manager.ts +++ b/src/sync-manager.ts @@ -440,6 +440,40 @@ export default class SyncManager { decodeBase64String(blob.content), ); + // Detect files modified directly on GitHub (via web UI or other means). + // The manifest only updates when syncing through this plugin, so we compare + // actual tree SHAs with manifest SHAs to catch external modifications. + await this.logger.info("Checking for remote changes outside manifest"); + Object.keys(files).forEach((filePath: string) => { + if (filePath === `${this.vault.configDir}/${MANIFEST_FILE_NAME}`) { + return; + } + + const actualRemoteSHA = files[filePath].sha; + const manifestEntry = remoteMetadata.files[filePath]; + + if (manifestEntry) { + if (manifestEntry.sha !== actualRemoteSHA) { + this.logger.info("Detected external change", { + filePath, + manifestSHA: manifestEntry.sha, + actualSHA: actualRemoteSHA, + }); + manifestEntry.sha = actualRemoteSHA; + manifestEntry.lastModified = Date.now(); + } + } else { + this.logger.info("Detected new file added externally", { filePath }); + remoteMetadata.files[filePath] = { + path: filePath, + sha: actualRemoteSHA, + dirty: false, + justDownloaded: false, + lastModified: Date.now(), + }; + } + }); + const conflicts = await this.findConflicts(remoteMetadata.files); // We treat every resolved conflict as an upload SyncAction, mainly cause