Skip to content

Commit 068b48c

Browse files
committed
Optimization of Git status (in Commit dialog)
Speeds up GitClient.getStatus() by deferring expensive evaluation of object Ids, which often compute file content hash, to evaluate them lazily only when needed. Additionally, skips calling isEntryIgnored, which recursively scans for .gitignore files up to the root directory, in case it's not needed at all. This saves additional few hundres of milliseconds. On Netbeans repository with a lot of files, this speeds up GitClient.getStatus() execution from 4 seconds to 1 second.
1 parent 2b92f87 commit 068b48c

1 file changed

Lines changed: 19 additions & 12 deletions

File tree

ide/libs.git/src/org/netbeans/libs/git/jgit/commands/StatusCommand.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.List;
3434
import java.util.Map;
3535
import java.util.Set;
36+
import java.util.function.Supplier;
3637
import java.util.logging.Level;
3738
import java.util.logging.Logger;
3839
import org.eclipse.jgit.diff.DiffEntry;
@@ -47,7 +48,9 @@
4748
import org.eclipse.jgit.lib.ObjectReader;
4849
import org.eclipse.jgit.lib.Repository;
4950
import org.eclipse.jgit.revwalk.RevWalk;
50-
import org.eclipse.jgit.treewalk.*;
51+
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
52+
import org.eclipse.jgit.treewalk.FileTreeIterator;
53+
import org.eclipse.jgit.treewalk.TreeWalk;
5154
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
5255
import org.eclipse.jgit.treewalk.filter.NotTreeFilter;
5356
import org.eclipse.jgit.treewalk.filter.OrTreeFilter;
@@ -180,16 +183,21 @@ protected void run () throws GitException {
180183
DirCacheEntry indexEntry = indexIterator != null ? indexIterator.getDirCacheEntry() : null;
181184
boolean isFolder = false;
182185
if (!symlink && treeWalk.isSubtree()) {
183-
if (mWorking == FileMode.TREE.getBits() && fti.isEntryIgnored()) {
184-
if (mHead != 0 || mIndex != 0) {
186+
if (mWorking == FileMode.TREE.getBits() && (mHead != 0 || mIndex != 0)) {
187+
// directory exists in commit or index: always enter; mark as ignored if applicable
188+
if (fti.isEntryIgnored()) {
185189
statusIndexWC = statusHeadWC = GitStatus.Status.STATUS_IGNORED;
186190
isFolder = true;
187191
treeWalk.enterSubtree();
188192
} else {
193+
treeWalk.enterSubtree();
194+
continue;
195+
}
196+
} else if (mWorking == FileMode.TREE.getBits() && fti.isEntryIgnored()) {
189197
Collection<TreeFilter> subTreeFilters = getSubtreeFilters(pathFilters, path);
190198
if (!subTreeFilters.isEmpty()) {
191199
// caller requested a status for a file under an ignored folder
192-
treeWalk.setFilter(AndTreeFilter.create(treeWalk.getFilter(), OrTreeFilter.create(NotTreeFilter.create(PathFilter.create(path)),
200+
treeWalk.setFilter(AndTreeFilter.create(treeWalk.getFilter(), OrTreeFilter.create(NotTreeFilter.create(PathFilter.create(path)),
193201
subTreeFilters.size() > 1 ? OrTreeFilter.create(subTreeFilters) : subTreeFilters.iterator().next())));
194202
treeWalk.enterSubtree();
195203
}
@@ -200,7 +208,6 @@ protected void run () throws GitException {
200208
} else {
201209
continue;
202210
}
203-
}
204211
} else {
205212
treeWalk.enterSubtree();
206213
continue;
@@ -217,11 +224,11 @@ protected void run () throws GitException {
217224
} else {
218225
statusIndexWC = GitStatus.Status.STATUS_ADDED;
219226
}
220-
} else if (!isExistingSymlink(mIndex, mWorking) && (differ(mIndex, mWorking, checkExecutable)
227+
} else if (!isExistingSymlink(mIndex, mWorking) && (differ(mIndex, mWorking, checkExecutable)
221228
|| (mWorking != 0 && mWorking != FileMode.TREE.getBits() && fti.isModified(indexEntry, true, od)))
222229
|| GitStatus.Status.STATUS_MODIFIED == getGitlinkStatus(
223-
mWorking, treeWalk.getObjectId(T_WORKSPACE),
224-
mIndex, treeWalk.getObjectId(T_INDEX))) {
230+
mWorking, () -> treeWalk.getObjectId(T_WORKSPACE),
231+
mIndex, () -> treeWalk.getObjectId(T_INDEX))) {
225232
statusIndexWC = GitStatus.Status.STATUS_MODIFIED;
226233
} else {
227234
statusIndexWC = GitStatus.Status.STATUS_NORMAL;
@@ -237,8 +244,8 @@ protected void run () throws GitException {
237244
&& (statusIndexWC != GitStatus.Status.STATUS_NORMAL || statusHeadIndex != GitStatus.Status.STATUS_NORMAL)
238245
&& !treeWalk.getObjectId(T_COMMIT).equals(fti.getEntryObjectId())))
239246
|| GitStatus.Status.STATUS_MODIFIED == getGitlinkStatus(
240-
mHead, treeWalk.getObjectId(T_WORKSPACE),
241-
mHead, treeWalk.getObjectId(T_COMMIT))) {
247+
mHead, () -> treeWalk.getObjectId(T_WORKSPACE),
248+
mHead, () -> treeWalk.getObjectId(T_COMMIT))) {
242249
statusHeadWC = GitStatus.Status.STATUS_MODIFIED;
243250
} else {
244251
statusHeadWC = GitStatus.Status.STATUS_NORMAL;
@@ -444,13 +451,13 @@ private void handleSymlink (List<GitStatus> symLinks, String workTreePath) {
444451
}
445452
}
446453

447-
private GitStatus.Status getGitlinkStatus (int mode1, ObjectId id1, int mode2, ObjectId id2) {
454+
private GitStatus.Status getGitlinkStatus (int mode1, Supplier<ObjectId> id1, int mode2, Supplier<ObjectId> id2) {
448455
if (mode1 == FileMode.TYPE_GITLINK || mode2 == FileMode.TYPE_GITLINK) {
449456
if (mode1 == FileMode.TYPE_MISSING) {
450457
return GitStatus.Status.STATUS_REMOVED;
451458
} else if (mode2 == FileMode.TYPE_MISSING) {
452459
return GitStatus.Status.STATUS_ADDED;
453-
} else if (!id1.equals(id2)) {
460+
} else if (!id1.get().equals(id2.get())) {
454461
return GitStatus.Status.STATUS_MODIFIED;
455462
}
456463
}

0 commit comments

Comments
 (0)