Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3-way diff #2

Open
ChristianWeissCG opened this issue Mar 9, 2019 · 1 comment
Open

3-way diff #2

ChristianWeissCG opened this issue Mar 9, 2019 · 1 comment

Comments

@ChristianWeissCG
Copy link

ChristianWeissCG commented Mar 9, 2019

I would love to see a 3-way diff:
json-cli threewaydiff base.json left.json right.json

And to get a combined patch for non-conflicting changes:

[
    {"value":4,"op":"test","path":"/key1/0"},
    {"value":5,"op":"replace","path":"/key1/0"},
    {"op":"remove","path":"/key2"},
    {"op":"remove","path":"/key3/sub0"},
    {"value":"a","op":"test","path":"/key3/sub1"},
    {"value":"c","op":"replace","path":"/key3/sub1"},
    {"value":"b","op":"test","path":"/key3/sub2"},
    {"value":false,"op":"replace","path":"/key3/sub2"},
    {"value":0,"op":"add","path":"/key3/sub3"},
    {"op":"remove","path":"/key4/1/b"},
    {"value":false,"op":"add","path":"/key4/1/c"},
    {"value":1,"op":"add","path":"/key4/2/c"},
    {"value":"wat","op":"add","path":"/key5"}
]

Or in case of a conflict:

[
    {"op":"conflict","path":"/key1/0","value_left":4,"value_right":5,"op_left":"replace","op_right":"replace"},
    {"op":"conflict","path":"/key2","value_left":4,"value_right":null,"op_left":"replace","op_right":"remove"},
    {"op":"remove","path":"/key3/sub0"},
    {"value":"a","op":"test","path":"/key3/sub1"},
    {"value":"c","op":"replace","path":"/key3/sub1"},
    {"value":"b","op":"test","path":"/key3/sub2"},
    {"value":false,"op":"replace","path":"/key3/sub2"},
    {"value":0,"op":"add","path":"/key3/sub3"},
    {"op":"remove","path":"/key4/1/b"},
    {"value":false,"op":"add","path":"/key4/1/c"},
    {"value":1,"op":"add","path":"/key4/2/c"},
    {"value":"wat","op":"add","path":"/key5"}
]

Interim patches for "left vs base" and "right vs base" are required. "op"=="test" can be ignored when combining the both patches to a 3-way-patch. If a "path" is touched by a single patch, then it can go directly to the 3-way-patch output. If a path is touched by both patches then it is a potential conflict. If "op" and "value" is equal on both patches then it is not a conflict and can be written as a single line to the 3-way-patch. Else it is a conflict and should be written like in the example:

[
...
{"op":"conflict","path":"/key1/0","value_left":4,"value_right":5,"op_left":"replace","op_right":"replace"}
...
]

This json-cli feature can help to write a 3-way-merge conflict auto resolver (wrapper script) e.g. for sops-encrypted json files.
On conflict this wrapper script can at least auto-merge non-conflicting changes and show the conflicts to the user for manual conflict resolution (e.g. via P4merge, KDiff3).

@vearutop
Copy link
Member

vearutop commented Mar 11, 2019

This is an interesting problem.

{"op":"conflict"} does not belong to JSON Patch RFC, I think we should not be breaking RFC compliance for such purpose.
What do you think if such 3-way-diff implemented in two parts: non-conflicting diff (a regular RFC patch) and conflicts collection ([{"op":"conflict"},...])?

Alternative approach to consider is to json-cli rearrange and pretty print left.json and right.json from base.json. That way you will receive json files that can be resolved with regular text diff.

Could you elaborate the expected usecase scenario? Not sure I can clearly understand how would you use [{"op":"conflict"},...] later in tooling flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants