From b48c5e823c3f9afefe8952b3c2306a0d85ee37ae Mon Sep 17 00:00:00 2001 From: arimu1 <19286898+arimu1@users.noreply.github.com> Date: Sun, 16 Aug 2026 08:03:02 +0700 Subject: [PATCH] WorkingTreeIterator: Fix relative core.excludesFile C Git resolves a relative core.excludesFile path against the repository work tree root. JGit passed null to Config.getPath, which uses the Java process current directory, so the same relative path was missed when status ran from a subdirectory. Fixes #280 Change-Id: I7cf1a7d768068b475388a81d274f92ef85743618 --- .../eclipse/jgit/api/StatusCommandTest.java | 22 ++++++++++++++- .../eclipse/jgit/ignore/IgnoreNodeTest.java | 28 ++++++++++++++++++- .../jgit/treewalk/WorkingTreeIterator.java | 7 +++-- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java index 19281f6c993..a8023562ea4 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, Christian Halstrick and others + * Copyright (C) 2011, 2026 Christian Halstrick and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -30,6 +30,26 @@ public class StatusCommandTest extends RepositoryTestCase { + @Test + public void testRelativeCoreExcludesFile() throws Exception { + try (Git git = new Git(db)) { + writeTrashFile("sub/myexclusions", "ignoring\n"); + FileBasedConfig config = db.getConfig(); + config.setString("core", null, "excludesFile", "sub/myexclusions"); + config.save(); + writeTrashFile("foo", "foo"); + writeTrashFile("ignoring", "foo"); + writeTrashFile("sub/foo", "foo"); + writeTrashFile("sub/ignoring", "foo"); + + Status stat = git.status().call(); + assertEquals(Sets.of("foo", "sub/foo", "sub/myexclusions"), + stat.getUntracked()); + assertEquals(Sets.of("ignoring", "sub/ignoring"), + stat.getIgnoredNotInIndex()); + } + } + @Test public void testEmptyStatus() throws NoWorkTreeException, GitAPIException { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java index ab08c997969..d5b3a524b38 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, Red Hat Inc. and others + * Copyright (C) 2010, 2026 Red Hat Inc. and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -58,6 +58,32 @@ public void closeWalk() { } } + @Test + public void testRelativeCoreExcludesFileResolvedAgainstWorkTree() + throws Exception { + // C Git resolves a relative core.excludesFile against the work tree + // root, not the process current directory. See + // https://github.com/eclipse-jgit/jgit/issues/280 + writeIgnoreFile("sub/myexclusions", "ignoring"); + db.getConfig().setString("core", null, "excludesFile", + "sub/myexclusions"); + db.getConfig().save(); + + writeTrashFile("foo", "foo"); + writeTrashFile("ignoring", "foo"); + writeTrashFile("sub/foo", "foo"); + writeTrashFile("sub/ignoring", "foo"); + + beginWalk(); + assertEntry(F, tracked, "foo"); + assertEntry(F, ignored, "ignoring"); + assertEntry(D, tracked, "sub"); + assertEntry(F, tracked, "sub/foo"); + assertEntry(F, ignored, "sub/ignoring"); + assertEntry(F, tracked, "sub/myexclusions"); + endWalk(); + } + @Test public void testSimpleRootGitIgnoreGlobalIgnore() throws IOException { writeIgnoreFile(".gitignore", "x"); 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 f16d800f630..bd1689d40c6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -2,7 +2,7 @@ * Copyright (C) 2008, Shawn O. Pearce * Copyright (C) 2010, Christian Halstrick * Copyright (C) 2010, Matthias Sohn - * Copyright (C) 2012, 2022, Robin Rosenberg and others + * Copyright (C) 2012, 2026, Robin Rosenberg and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -1291,9 +1291,12 @@ private static class RootIgnoreNode extends PerDirectoryIgnoreNode { IgnoreNode load(IgnoreNode parent) throws IOException { IgnoreNode coreExclude = new IgnoreNodeWithParent(parent); FS fs = repository.getFS(); + // C Git resolves a relative core.excludesFile against the work + // tree root (it chdirs there). Do not use the process CWD. Path path = repository.getConfig().getPath( ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_EXCLUDESFILE, fs, null, null); + ConfigConstants.CONFIG_KEY_EXCLUDESFILE, fs, + repository.getWorkTree(), null); if (path != null) { if (Files.exists(path)) { loadRulesFromFile(coreExclude, path.toFile());