From 7a3b93cbedc9c4070c19ee8878adeb8455b61c21 Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Mon, 21 Oct 2019 22:28:50 +0200 Subject: [PATCH] IndexDiff/SubmoduleWalk: handle submodule..ignore correctly IndexDiff would apply ignore mode ALL from .gitmodules to all remaining submodules, and would ignore other settings from .gitignore and always apply the setting defined on the IndexDiff instead. Correct that. In canonical git the ignore setting from .gitmodules can also be overridden by .git/config.[1] Implement that override in SubmoduleWalk. [1] https://git-scm.com/docs/gitmodules#Documentation/gitmodules.txt-submoduleltnamegtignore Bug: 521613 Change-Id: I9199fd447e41c7838924856dce40678370b66395 Signed-off-by: Thomas Wolf --- .../jgit/lib/IndexDiffSubmoduleTest.java | 77 +++++++++++++++++++ .../src/org/eclipse/jgit/lib/IndexDiff.java | 6 +- .../eclipse/jgit/submodule/SubmoduleWalk.java | 7 ++ 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java index fa7f5ab52..014a58772 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java @@ -60,9 +60,11 @@ import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.submodule.SubmoduleWalk.IgnoreSubmoduleMode; import org.eclipse.jgit.treewalk.FileTreeIterator; import org.junit.Before; +import org.junit.Test; import org.junit.experimental.theories.DataPoints; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; @@ -295,4 +297,79 @@ public class IndexDiffSubmoduleTest extends RepositoryTestCase { indexDiff.getAdded().toString()); } + @Test + public void testIndexDiffTwoSubmodules() throws Exception { + // Create a second submodule + try (Repository submodule2 = createWorkRepository()) { + JGitTestUtil.writeTrashFile(submodule2, "fileInSubmodule2", + "submodule2"); + Git subGit = Git.wrap(submodule2); + subGit.add().addFilepattern("fileInSubmodule2").call(); + subGit.commit().setMessage("add file to submodule2").call(); + + try (Repository sub2 = Git.wrap(db) + .submoduleAdd().setPath("modules/submodule2") + .setURI(submodule2.getDirectory().toURI().toString()) + .call()) { + writeTrashFile("fileInRoot", "root+"); + Git rootGit = Git.wrap(db); + rootGit.add().addFilepattern("fileInRoot").call(); + rootGit.commit().setMessage("add submodule2 and root file") + .call(); + // Now change files in both submodules + JGitTestUtil.writeTrashFile(submodule_db, "fileInSubmodule", + "submodule changed"); + JGitTestUtil.writeTrashFile(sub2, "fileInSubmodule2", + "submodule2 changed"); + // Set up .gitmodules + FileBasedConfig gitmodules = new FileBasedConfig( + new File(db.getWorkTree(), Constants.DOT_GIT_MODULES), + db.getFS()); + gitmodules.load(); + gitmodules.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, + "modules/submodule", ConfigConstants.CONFIG_KEY_IGNORE, + "all"); + gitmodules.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, + "modules/submodule2", ConfigConstants.CONFIG_KEY_IGNORE, + "none"); + gitmodules.save(); + IndexDiff indexDiff = new IndexDiff(db, Constants.HEAD, + new FileTreeIterator(db)); + assertTrue(indexDiff.diff()); + String[] modified = indexDiff.getModified() + .toArray(new String[0]); + Arrays.sort(modified); + assertEquals("[.gitmodules, modules/submodule2]", + Arrays.toString(modified)); + // Try again with "dirty" + gitmodules.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, + "modules/submodule", ConfigConstants.CONFIG_KEY_IGNORE, + "dirty"); + gitmodules.save(); + indexDiff = new IndexDiff(db, Constants.HEAD, + new FileTreeIterator(db)); + assertTrue(indexDiff.diff()); + modified = indexDiff.getModified().toArray(new String[0]); + Arrays.sort(modified); + assertEquals("[.gitmodules, modules/submodule2]", + Arrays.toString(modified)); + // Test the config override + StoredConfig cfg = db.getConfig(); + cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, + "modules/submodule", ConfigConstants.CONFIG_KEY_IGNORE, + "none"); + cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, + "modules/submodule2", ConfigConstants.CONFIG_KEY_IGNORE, + "all"); + cfg.save(); + indexDiff = new IndexDiff(db, Constants.HEAD, + new FileTreeIterator(db)); + assertTrue(indexDiff.diff()); + modified = indexDiff.getModified().toArray(new String[0]); + Arrays.sort(modified); + assertEquals("[.gitmodules, modules/submodule]", + Arrays.toString(modified)); + } + } + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java index b87a031f5..4e9fab7b5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java @@ -535,10 +535,10 @@ public class IndexDiff { } if (ignoreSubmoduleMode != IgnoreSubmoduleMode.ALL) { - IgnoreSubmoduleMode localIgnoreSubmoduleMode = ignoreSubmoduleMode; try (SubmoduleWalk smw = new SubmoduleWalk(repository)) { smw.setTree(new DirCacheIterator(dirCache)); while (smw.next()) { + IgnoreSubmoduleMode localIgnoreSubmoduleMode = ignoreSubmoduleMode; try { if (localIgnoreSubmoduleMode == null) localIgnoreSubmoduleMode = smw.getModulesIgnore(); @@ -558,7 +558,7 @@ public class IndexDiff { && !subHead.equals(smw.getObjectId())) { modified.add(subRepoPath); recordFileMode(subRepoPath, FileMode.GITLINK); - } else if (ignoreSubmoduleMode != IgnoreSubmoduleMode.DIRTY) { + } else if (localIgnoreSubmoduleMode != IgnoreSubmoduleMode.DIRTY) { IndexDiff smid = submoduleIndexDiffs .get(smw.getPath()); if (smid == null) { @@ -569,7 +569,7 @@ public class IndexDiff { submoduleIndexDiffs.put(subRepoPath, smid); } if (smid.diff()) { - if (ignoreSubmoduleMode == IgnoreSubmoduleMode.UNTRACKED + if (localIgnoreSubmoduleMode == IgnoreSubmoduleMode.UNTRACKED && smid.getAdded().isEmpty() && smid.getChanged().isEmpty() && smid.getConflicting().isEmpty() diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java index e5559dea0..3eca08a44 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java @@ -735,6 +735,13 @@ public class SubmoduleWalk implements AutoCloseable { */ public IgnoreSubmoduleMode getModulesIgnore() throws IOException, ConfigInvalidException { + IgnoreSubmoduleMode mode = repoConfig.getEnum( + IgnoreSubmoduleMode.values(), + ConfigConstants.CONFIG_SUBMODULE_SECTION, getModuleName(), + ConfigConstants.CONFIG_KEY_IGNORE, null); + if (mode != null) { + return mode; + } lazyLoadModulesConfig(); return modulesConfig.getEnum(IgnoreSubmoduleMode.values(), ConfigConstants.CONFIG_SUBMODULE_SECTION, getModuleName(),