From d9c0629ffe45ba96f853672268c391dd7caa82fe Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Wed, 20 Jul 2022 18:30:18 +0200 Subject: [PATCH] Fix adding symlinks to the index when core.symlinks=false With core.symlinks=false, symlinks are checked out as plain files. When such a file is re-added to the index, and the index already contains a symlink there, add the file as a symlink. Previous code changed the index entry to a regular file. Bug: 580412 Change-Id: I5497bedc3da89c8b10120b8077c56bc5b67cb791 Signed-off-by: Thomas Wolf --- .../org/eclipse/jgit/api/AddCommandTest.java | 41 +++++++++++++++++++ .../jgit/treewalk/WorkingTreeIterator.java | 6 +++ 2 files changed, 47 insertions(+) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java index 5dfdfcfe6..57661a7ec 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java @@ -15,13 +15,16 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.file.Files; import java.util.Set; +import org.eclipse.jgit.api.ResetCommand.ResetType; import org.eclipse.jgit.api.errors.FilterFailedException; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.NoFilepatternException; @@ -34,6 +37,7 @@ import org.eclipse.jgit.lfs.BuiltinLFS; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.CoreConfig.SymLinks; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; @@ -99,6 +103,43 @@ public void testAddExistingSingleFile() throws IOException, GitAPIException { } } + @Test + public void testAddLink() throws IOException, GitAPIException { + assumeTrue(db.getFS().supportsSymlinks()); + try (Git git = new Git(db)) { + writeTrashFile("a.txt", "a"); + File link = new File(db.getWorkTree(), "link"); + db.getFS().createSymLink(link, "a.txt"); + git.add().addFilepattern(".").call(); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:120000, content:a.txt]", + indexState(CONTENT)); + git.commit().setMessage("link").call(); + StoredConfig config = db.getConfig(); + config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, SymLinks.FALSE); + config.save(); + Files.delete(link.toPath()); + git.reset().setMode(ResetType.HARD).call(); + assertTrue(Files.isRegularFile(link.toPath())); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:120000, content:a.txt]", + indexState(CONTENT)); + writeTrashFile("link", "b.txt"); + git.add().addFilepattern("link").call(); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:120000, content:b.txt]", + indexState(CONTENT)); + config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, SymLinks.TRUE); + config.save(); + git.add().addFilepattern("link").call(); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:100644, content:b.txt]", + indexState(CONTENT)); + } + } + @Test public void testCleanFilter() throws IOException, GitAPIException { writeTrashFile(".gitattributes", "*.txt filter=tstFilter"); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java index b108b0a95..d8a61ec97 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -1004,6 +1004,12 @@ public FileMode getIndexFileMode(DirCacheIterator indexIter) { return wtMode; } final FileMode iMode = indexIter.getEntryFileMode(); + if (iMode == FileMode.SYMLINK + && getOptions().getSymLinks() == SymLinks.FALSE + && (wtMode == FileMode.REGULAR_FILE + || wtMode == FileMode.EXECUTABLE_FILE)) { + return iMode; + } if (getOptions().isFileMode() && iMode != FileMode.GITLINK && iMode != FileMode.TREE) { return wtMode; }