Bug 580347 - Merge Symlink Conflicts Fail
Summary: Merge Symlink Conflicts Fail
Status: RESOLVED FIXED
Alias: None
Product: JGit
Classification: Technology
Component: JGit (show other bugs)
Version: 6.2   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 6.3   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-07-06 11:49 EDT by Dave Hawkins CLA
Modified: 2022-09-07 15:16 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Hawkins CLA 2022-07-06 11:49:42 EDT
When there is a merge conflict involving symlinks, JGit treats the symlink as a normal file and attempts write the conflict diff to it. This either creates a new file if the target doesn't currently exist, corrupts a targeted file or fails for a targeted directory.

Steps:
1) Create git repository
2) Create symlink "link" with target "target"
3) For each of no target objects; root with empty files "target", "target1" and "target2"; root with empty directories "target", "target1" and "target2"
   a) Commit everything to git
   b) Checkout new branch test_merge_1
   c) Change symlink to "target1"
   d) Commit change
   e) Checkout new branch test_merge_2 starting from "master"
   f) Change symlink to "target2"
   g) Commit change
   h) Merge test_merge_1

This should report that there is a conflict, but leave the working tree unchanged, including in the case where core.symlinks = false.

For directories the following exception is thrown:
Caused by: java.io.FileNotFoundException: <git root>/link (Is a directory)
        at java.base/java.io.FileOutputStream.open0(Native Method)
        at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
        at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
        at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:184)
        at org.eclipse.jgit.merge.ResolveMerger.writeMergedFile(ResolveMerger.java:1105)
        at org.eclipse.jgit.merge.ResolveMerger.updateIndex(ResolveMerger.java:1044)
        at org.eclipse.jgit.merge.ResolveMerger.processEntry(ResolveMerger.java:857)
        at org.eclipse.jgit.merge.ResolveMerger.mergeTreeWalk(ResolveMerger.java:1429)
        at org.eclipse.jgit.merge.ResolveMerger.mergeTrees(ResolveMerger.java:1371)
        at org.eclipse.jgit.merge.ResolveMerger.mergeImpl(ResolveMerger.java:393)
        at org.eclipse.jgit.merge.Merger.merge(Merger.java:233)
        at org.eclipse.jgit.merge.Merger.merge(Merger.java:186)
        at org.eclipse.jgit.merge.ThreeWayMerger.merge(ThreeWayMerger.java:96)
        at org.eclipse.jgit.api.MergeCommand.call(MergeCommand.java:345)

Presumably ResolveMerger needs to check whether the object is a symlink and do nothing in that case.

I haven't checked rebase, but I guess that would have a similar issue.

In my case I can workaround this problem by using core.symlinks = false. It's not quite right, but it doesn't fall over or write to arbitrary locations.
Comment 1 Dave Hawkins CLA 2022-07-15 04:56:18 EDT
To clarify the final point in my previous comment. Conflicts with core.symlinks = false are treated as regular file conflicts with the standard conflict markers by JGit. git doesn't do this and leaves the content as for core.symlinks = true.
Comment 2 Eclipse Genie CLA 2022-08-17 16:45:23 EDT
New Gerrit change created: https://git.eclipse.org/r/c/jgit/jgit/+/195219