RickStrahl / MarkdownMonster

An extensible Markdown Editor, Viewer and Weblog Publisher for Windows
https://markdownmonster.west-wind.com
Other
1.58k stars 236 forks source link

Issue with BeyondCompare and File Save Operations #1100

Closed RickStrahl closed 5 months ago

RickStrahl commented 5 months ago

When using BeyondCompare to do file comparisons, and then saving changes to disk that match the open file in the editor, MM doesn't see the changes and doesn't update unchanged documents the same way as other programs (like VS Code) do.

This also manifests in funky behavior when doing the 'Compare' Diff operation when saving a document as merged changes in BeyondCompare end up not showing up in MM unless the document is reloaded.

RickStrahl commented 5 months ago

The issue in this case is that BeyondCompare does not 'change' a file when writing it but rather copies to a new file and then renames the file. MM uses a FileWatcher, but we were using only the 'Change' handler to capture changes to files. These don't trigger with BeyondCompare's update operation due to the copy/rename flow.

This issue has been fixed now, so Saving in BeyondCompare now shows up in MM if the document is not changed.

However there are other related issues...

RickStrahl commented 5 months ago

However, there's another problem related to the Compare save behavior with BYC.

Scenario:

Problem:

The issue here is that we now can't get a notification of any sort from BYC that we want to use their changes and throw out our changes because the file is already up to date. It works if we merge changes into theirs or we make a manual change in which case the file is changed and we see the updated change in MM as the document is reloaded.

But that one scenario where we compare and then want to accept Theirs without further changes doesn't notify.

Options:

This works if you immediately close BYC. But t relies on closing BYC which can be problematic especially if it was previously open (it's a singleton application as are most Diff tools). So you may never end up closing BYC. Further if you don't close the check for close is delayed and may now execute at the wrong time.

I'm still trying to figure out a way to make this work.

Some other ideas:

The simplest solution would be if we could trick BeyondCompare to assume the current disk file is dirty so that a save operation would trigger a file change/rename event, but I can't figure out how to do that without affecting other applications that might be monitoring. Touching the file would trigger a file change event in VS Code for example.

Lots of ideas, but none that are really solving the problem cleanly.

Any ideas welcome.

RickStrahl commented 5 months ago

After playing around with this a whole bunch yesterday trying a whole bunch of different things, I think it comes down to only two possible solutions when using an external editor:

  1. Save our current content to .mdours.diff.md and leave on disk file intact then open BYC
  2. Copy file on disk to .mdTheirs.diff.md and save ours to file then open BYC

You can then use BYC to compare and if necessary merge the file and save and it would reflect in the editor. The idea is that we are working with the actual file on disk and can use the standard MM mechanism to sync back into the document.

Why not use two Temp Files to Compare?

Anything else that uses only temporary files is a problem because we have no way to tell when we're done and can result in potentially capturing changes from disk that are no longer relevant or even loaded in the editor.

So I think the only safe solution is to actually Diff the file on disk and as best as possible have file represent the intended state based on 1 or 2 and then let the editor auto-detect the on-disk changes as it normally does.

Comparing both of the above solutions

Advantages:

In both scenarios we're working with the actual file on disk, so what you see is what you get both in the Diff tool and in the editor.

  1. properly reflects current on-disk file state.
  2. correctly represents intent of saving current file and merging changes from file on disk

Downsides:

1) We load the file from disk into the editor which changes the active editor content by default which puts the reliance on making changes in BYC even to get back to the original content. (You can Undo/Ctrl-z, but that's not obvious).

2) We basically copy out the original file content and if we abort or do nothing we've now overwritten the file. Same scenario as 1. but you now rely on BYC update to get back to the original file content. The other downside is that this may result in external applications immediately seeing our saved file content before we're done editing/merging.

I'm leaning to 2. as it more likely represent the intent of the situation - you're trying to save and potentially merge changes from the file on disk. And you can revert back to the external file in BYC.

Neither of these is great frankly because they are somewhat ambiguous. For MM 2. is definitely a better choice, but for other apps it may be more problematic.

I've experimented with copying both files and then editing in BYC and detecting changes. While I can detect changes, I've not found a reliable way to detect when the user is done editing/merging to accept the changes. Can't wait on the process because BYC is a singleton that launches a separate instance (ie. launch process often closes immediately) and even if that worked you can have multiple tabs open so you wouldn't close. Detecting Save operations works, but when do we stop listening? Since the window can be open indefinitely the document may not even be open anymore in MM.

So I think the only solution is to edit the actual file on disk and then let the current file change detection manage how the editor handles the change on disk. Again that makes me think the 2. is the best solution to this.

RickStrahl commented 5 months ago

Updated in 3.2.9.5 and later to work with option 2.