diff options
8 files changed, 244 insertions, 196 deletions
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTest.java index 66bb5c7fbd..4668849c08 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTest.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org> + * Copyright (C) 2011, 2013 Dariusz Luksza <dariusz@luksza.org> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,13 +8,20 @@ *******************************************************************************/ package org.eclipse.egit.ui.internal.synchronize.model; +import static org.eclipse.jgit.junit.JGitTestUtil.writeTrashFile; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import java.io.File; +import java.util.Map; +import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change; +import org.eclipse.egit.core.synchronize.StagedChangeCache; import org.eclipse.egit.ui.Activator; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.storage.file.FileRepository; import org.junit.BeforeClass; import org.junit.Test; @@ -93,6 +100,30 @@ public class GitModelCacheTest extends GitModelTestCase { assertFalse(actual); } + @Test + public void shouldReturnChildren() throws Exception { + FileRepository repo = lookupRepository(leftRepoFile); + writeTrashFile(repo, "dir/a.txt", "trash"); + writeTrashFile(repo, "dir/b.txt", "trash"); + writeTrashFile(repo, "dir/c.txt", "trash"); + writeTrashFile(repo, "dir/d.txt", "trash"); + new Git(repo).add().addFilepattern("dir").call(); + + Map<String, Change> changes = StagedChangeCache.build(repo); + assertEquals(4, changes.size()); + + GitModelCache cache = new GitModelCache(createModelRepository(), repo, + changes); + + GitModelObject[] cacheChildren = cache.getChildren(); + assertEquals(1, cacheChildren.length); + GitModelObject dir = cacheChildren[0]; + assertEquals("dir", dir.getName()); + + GitModelObject[] dirChildren = dir.getChildren(); + assertEquals(4, dirChildren.length); + } + @BeforeClass public static void setupEnvironment() throws Exception { leftRepoFile = createProjectAndCommitToRepository(); diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTreeTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTreeTest.java index 25aa328033..20f2198e47 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTreeTest.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTreeTest.java @@ -15,7 +15,7 @@ import static org.mockito.Mockito.mock; import org.eclipse.core.runtime.IPath; import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change; import org.eclipse.egit.ui.Activator; -import org.eclipse.egit.ui.internal.synchronize.model.GitModelCache.FileModelFactory; +import org.eclipse.egit.ui.internal.synchronize.model.TreeBuilder.FileModelFactory; import org.eclipse.jgit.lib.Repository; import org.junit.BeforeClass; import org.junit.Test; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCache.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCache.java index d44013d2a8..d0f18c5919 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCache.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCache.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org> + * Copyright (C) 2010, 2013 Dariusz Luksza <dariusz@luksza.org> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,17 +8,15 @@ *******************************************************************************/ package org.eclipse.egit.ui.internal.synchronize.model; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Map.Entry; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change; import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.synchronize.model.TreeBuilder.FileModelFactory; +import org.eclipse.egit.ui.internal.synchronize.model.TreeBuilder.TreeModelFactory; import org.eclipse.jgit.lib.Repository; /** @@ -28,45 +26,9 @@ public class GitModelCache extends GitModelObjectContainer { private final Path location; - private final FileModelFactory fileFactory; - - private final Map<String, GitModelCacheTree> cacheTreeMap; - private final Repository repo; - private final Map<String, Change> cache; - - /** - * This interface enables creating proper instance of {@link GitModelBlob} - * for cached and working files. In case of working files the left side - * content of Compare View is loaded from local hard drive. - */ - protected interface FileModelFactory { - /** - * Creates proper instance of {@link GitModelBlob} for cache and working - * tree model representation - * - * @param objParent - * parent object - * @param repo - * repository associated with file that will be created - * @param change - * change associated with file that will be created - * @param fullPath - * absolute path - * @return instance of {@link GitModelBlob} - */ - GitModelBlob createFileModel(GitModelObjectContainer objParent, - Repository repo, Change change, IPath fullPath); - - /** - * Distinguish working tree from changed/staged tree - * - * @return {@code true} when this tree is working tree, {@code false} - * when it is a cached tree - */ - boolean isWorkingTree(); - } + private GitModelObject[] children; /** * Constructs model node that represents current status of Git cache. @@ -100,19 +62,27 @@ public class GitModelCache extends GitModelObjectContainer { * parent object * @param repo * repository associated with this object - * @param cache + * @param changes * list of changes associated with this object * @param fileFactory * leaf instance factory */ - protected GitModelCache(GitModelRepository parent, Repository repo, Map<String, Change> cache, - FileModelFactory fileFactory) { + protected GitModelCache(GitModelRepository parent, final Repository repo, + Map<String, Change> changes, final FileModelFactory fileFactory) { super(parent); this.repo = repo; - this.cache = cache; - this.fileFactory = fileFactory; - cacheTreeMap = new HashMap<String, GitModelCacheTree>(); - location = new Path(repo.getWorkTree().toString()); + this.location = new Path(repo.getWorkTree().toString()); + + this.children = TreeBuilder.build(this, repo, changes, fileFactory, + new TreeModelFactory() { + public GitModelTree createTreeModel( + GitModelObjectContainer parentObject, + IPath fullPath, + int kind) { + return new GitModelCacheTree(parentObject, repo, + fullPath, fileFactory); + } + }); } @Override @@ -122,17 +92,7 @@ public class GitModelCache extends GitModelObjectContainer { @Override public GitModelObject[] getChildren() { - List<GitModelObject> result = new ArrayList<GitModelObject>(); - - for (Entry<String, Change> cacheEntry : cache.entrySet()) { - GitModelObject entry = extractFromCache(cacheEntry.getValue(), cacheEntry.getKey()); - if (entry == null) - continue; - - result.add(entry); - } - - return result.toArray(new GitModelObject[result.size()]); + return children; } @Override @@ -176,34 +136,10 @@ public class GitModelCache extends GitModelObjectContainer { @Override public void dispose() { - for (GitModelTree modelTree : cacheTreeMap.values()) - modelTree.dispose(); - - cache.clear(); - cacheTreeMap.clear(); - } - - private GitModelObject extractFromCache(Change change, String path) { - if (path.contains("/")) //$NON-NLS-1$ - return handleCacheTree(change, path); - - return fileFactory.createFileModel(this, repo, change, - location.append(path)); - } - - private GitModelObject handleCacheTree(Change change, String path) { - int firstSlash = path.indexOf("/");//$NON-NLS-1$ - String pathKey = path.substring(0, firstSlash); - GitModelCacheTree cacheTree = cacheTreeMap.get(pathKey); - if (cacheTree == null) { - IPath newPath = location.append(pathKey); - cacheTree = new GitModelCacheTree(this, repo, newPath, fileFactory); - cacheTreeMap.put(pathKey, cacheTree); + if (children != null) { + for (GitModelObject object : children) + object.dispose(); + children = null; } - - cacheTree.addChild(change, path.substring(firstSlash + 1)); - - return cacheTree; } - } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTree.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTree.java index a5a9ed6bb4..94e488d162 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTree.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheTree.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org> + * Copyright (C) 2010, 2013 Dariusz Luksza <dariusz@luksza.org> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,13 +11,8 @@ package org.eclipse.egit.ui.internal.synchronize.model; import static org.eclipse.compare.structuremergeviewer.Differencer.CHANGE; import static org.eclipse.compare.structuremergeviewer.Differencer.RIGHT; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - import org.eclipse.core.runtime.IPath; -import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change; -import org.eclipse.egit.ui.internal.synchronize.model.GitModelCache.FileModelFactory; +import org.eclipse.egit.ui.internal.synchronize.model.TreeBuilder.FileModelFactory; import org.eclipse.jgit.lib.Repository; /** @@ -28,10 +23,6 @@ public class GitModelCacheTree extends GitModelTree { private final FileModelFactory factory; - private final Map<String, GitModelObject> cacheTreeMap; - - private final Repository repo; - /** * @param parent * parent object @@ -44,16 +35,7 @@ public class GitModelCacheTree extends GitModelTree { public GitModelCacheTree(GitModelObjectContainer parent, Repository repo, IPath fullPath, FileModelFactory factory) { super(parent, fullPath, RIGHT | CHANGE); - this.repo = repo; this.factory = factory; - cacheTreeMap = new HashMap<String, GitModelObject>(); - } - - @Override - public GitModelObject[] getChildren() { - Collection<GitModelObject> values = cacheTreeMap.values(); - - return values.toArray(new GitModelObject[values.size()]); } @Override @@ -92,26 +74,4 @@ public class GitModelCacheTree extends GitModelTree { return factory.isWorkingTree(); } - void addChild(Change change, String nestedPath) { - String pathKey; - int firstSlash = nestedPath.indexOf("/"); //$NON-NLS-1$ - if (firstSlash > -1) - pathKey = nestedPath.substring(0, firstSlash); - else - pathKey = nestedPath; - - IPath fullPath = getLocation().append(pathKey); - if (nestedPath.contains("/")) { //$NON-NLS-1$ - GitModelCacheTree cacheEntry = (GitModelCacheTree) cacheTreeMap - .get(pathKey); - if (cacheEntry == null) { - cacheEntry = new GitModelCacheTree(this, repo, fullPath, factory); - cacheTreeMap.put(pathKey, cacheEntry); - } - cacheEntry.addChild(change, nestedPath.substring(firstSlash + 1)); - } else - cacheTreeMap.put(pathKey, - factory.createFileModel(this, repo, change, fullPath)); - } - } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCommit.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCommit.java index 5bbc102638..91ee7df456 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCommit.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCommit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org> + * Copyright (C) 2010, 2013 Dariusz Luksza <dariusz@luksza.org> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,18 +8,14 @@ *******************************************************************************/ package org.eclipse.egit.ui.internal.synchronize.model; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change; import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Commit; +import org.eclipse.egit.ui.internal.synchronize.model.TreeBuilder.FileModelFactory; +import org.eclipse.egit.ui.internal.synchronize.model.TreeBuilder.TreeModelFactory; import org.eclipse.jgit.lib.Repository; /** @@ -34,7 +30,7 @@ public class GitModelCommit extends GitModelObjectContainer implements private final IProject[] projects; - private final Map<String, GitModelObject> cachedTreeMap = new HashMap<String, GitModelObject>(); + private GitModelObject[] children; /** * @param parent @@ -81,16 +77,30 @@ public class GitModelCommit extends GitModelObjectContainer implements @Override public GitModelObject[] getChildren() { - List<GitModelObject> result = new ArrayList<GitModelObject>(); + if (children == null) + children = createChildren(); + return children; + } - if (commit.getChildren() != null) // prevent from NPE in empty commits - for (Entry<String, Change> cacheEntry : commit.getChildren().entrySet()) { - GitModelObject nested = addChild(cacheEntry.getValue(), cacheEntry.getKey()); - if (nested != null) - result.add(nested); + private GitModelObject[] createChildren() { + FileModelFactory fileModelFactory = new FileModelFactory() { + public GitModelBlob createFileModel(GitModelObjectContainer parent, + Repository repository, Change change, IPath fullPath) { + return new GitModelBlob(parent, repository, change, fullPath); } - return result.toArray(new GitModelObject[result.size()]); + public boolean isWorkingTree() { + return false; + } + }; + TreeModelFactory treeModelFactory = new TreeModelFactory() { + public GitModelTree createTreeModel(GitModelObjectContainer parent, + IPath fullPath, int kind) { + return new GitModelTree(parent, fullPath, kind); + } + }; + return TreeBuilder.build(this, repo, commit.getChildren(), + fileModelFactory, treeModelFactory); } /** @@ -102,10 +112,11 @@ public class GitModelCommit extends GitModelObjectContainer implements @Override public void dispose() { - for (GitModelObject value : cachedTreeMap.values()) - value.dispose(); - - cachedTreeMap.clear(); + if (children != null) { + for (GitModelObject child : children) + child.dispose(); + children = null; + } } @Override @@ -134,36 +145,4 @@ public class GitModelCommit extends GitModelObjectContainer implements return "ModelCommit[" + commit.getId() + "]"; //$NON-NLS-1$//$NON-NLS-2$ } - private GitModelObject addChild(Change change, String nestedPath) { - GitModelObject firstObject = null; - IPath tmpLocation = getLocation(); - String[] segments = nestedPath.split("/"); //$NON-NLS-1$ - GitModelObjectContainer tmpPartent = this; - Map<String, GitModelObject> tmpCache = cachedTreeMap; - - for (int i = 0; i < segments.length; i++) { - String segment = segments[i]; - tmpLocation = tmpLocation.append(segment); - if (i < segments.length - 1) { - GitModelTree tree = (GitModelTree) tmpCache.get(segment); - if (tree == null) { - tree = new GitModelTree(tmpPartent, tmpLocation, change.getKind()); - tmpCache.put(segment, tree); - } - tmpPartent = tree; - tmpCache = tree.cachedTreeMap; - if (i == 0) - firstObject = tmpPartent; - } else { // handle last segment, it should be a file name - GitModelBlob blob = new GitModelBlob(tmpPartent, repo, change, - tmpLocation); - tmpCache.put(segment, blob); - if (i == 0) - firstObject = blob; - } - } - - return firstObject; - } - } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelTree.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelTree.java index 0d4290a721..32154d20ed 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelTree.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelTree.java @@ -1,6 +1,5 @@ /******************************************************************************* - - * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org> + * Copyright (C) 2010, 2013 Dariusz Luksza <dariusz@luksza.org> and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -9,9 +8,7 @@ *******************************************************************************/ package org.eclipse.egit.ui.internal.synchronize.model; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.List; import org.eclipse.core.runtime.IPath; @@ -27,7 +24,7 @@ public class GitModelTree extends GitModelObjectContainer { */ protected final IPath path; - final Map<String, GitModelObject> cachedTreeMap = new HashMap<String, GitModelObject>(); + private GitModelObject[] children; /** * @param parent @@ -66,9 +63,7 @@ public class GitModelTree extends GitModelObjectContainer { @Override public GitModelObject[] getChildren() { - Collection<GitModelObject> values = cachedTreeMap.values(); - - return values.toArray(new GitModelObject[values.size()]); + return children; } @Override @@ -78,10 +73,11 @@ public class GitModelTree extends GitModelObjectContainer { @Override public void dispose() { - for (GitModelObject value : cachedTreeMap.values()) - value.dispose(); - - cachedTreeMap.clear(); + if (children != null) { + for (GitModelObject object : children) + object.dispose(); + children = null; + } } @Override @@ -120,4 +116,8 @@ public class GitModelTree extends GitModelObjectContainer { return "ModelTree[location=" + getLocation() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } + void setChildren(List<GitModelObject> children) { + this.children = children.toArray(new GitModelObject[children.size()]); + } + } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingTree.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingTree.java index f61c127641..ecd47dc708 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingTree.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingTree.java @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org> * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com> + * Copyright (C) 2013, Robin Stocker <robin@nibor.org> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,6 +16,7 @@ import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.runtime.IPath; import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change; import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.synchronize.model.TreeBuilder.FileModelFactory; import org.eclipse.jgit.lib.Repository; /** diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/TreeBuilder.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/TreeBuilder.java new file mode 100644 index 0000000000..aefa033681 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/TreeBuilder.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (C) 2013 Robin Stocker <robin@nibor.org> + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.egit.ui.internal.synchronize.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change; +import org.eclipse.jgit.lib.Repository; + +/** + * For building trees of directory and file nodes out of a flat list of changes. + */ +class TreeBuilder { + + /** + * This interface enables creating the right instances of + * {@link GitModelBlob} for files. + */ + interface FileModelFactory { + /** + * Creates proper instance of {@link GitModelBlob} for file nodes + * + * @param parent + * parent object + * @param repo + * repository associated with file that will be created + * @param change + * change associated with file that will be created + * @param fullPath + * absolute path + * @return instance of {@link GitModelBlob} + */ + GitModelBlob createFileModel(GitModelObjectContainer parent, + Repository repo, Change change, IPath fullPath); + + /** + * Distinguish working tree from changed/staged tree + * + * @return {@code true} when this tree is working tree, {@code false} + * when it is a cached tree + */ + boolean isWorkingTree(); + } + + /** + * Interface for creating the desired instances of {@link GitModelTree}. + */ + interface TreeModelFactory { + GitModelTree createTreeModel(GitModelObjectContainer parent, + IPath fullPath, int kind); + } + + /** + * + * @param root + * the root node of the tree to build, which will become the + * parent of the first level of children + * @param repo + * @param changes + * @param fileFactory + * @param treeFactory + * @return the children of the root nodes + */ + public static GitModelObject[] build(final GitModelObjectContainer root, + final Repository repo, final Map<String, Change> changes, + final FileModelFactory fileFactory, + final TreeModelFactory treeFactory) { + + if (changes == null || changes.isEmpty()) + return new GitModelObject[] {}; + + final IPath rootPath = new Path(repo.getWorkTree() + .getAbsolutePath()); + final List<GitModelObject> rootChildren = new ArrayList<GitModelObject>(); + + final Map<IPath, Node> nodes = new HashMap<IPath, Node>(); + + for (Map.Entry<String, Change> entry : changes.entrySet()) { + String repoRelativePath = entry.getKey(); + Change change = entry.getValue(); + + GitModelObjectContainer parent = root; + List<GitModelObject> children = rootChildren; + IPath path = rootPath; + + String[] segments = repoRelativePath.split("/"); //$NON-NLS-1$ + + for (int i = 0; i < segments.length; i++) { + path = path.append(segments[i]); + + // Changes represent files, so the last segment is the file name + boolean fileNode = (i == segments.length - 1); + if (!fileNode) { + Node node = nodes.get(path); + if (node == null) { + GitModelTree tree = treeFactory.createTreeModel(parent, + path, change.getKind()); + node = new Node(tree); + nodes.put(path, node); + children.add(tree); + } + parent = node.tree; + children = node.children; + } else { + GitModelBlob file = fileFactory.createFileModel(parent, + repo, change, path); + children.add(file); + } + } + } + + for (Node object : nodes.values()) { + GitModelTree tree = object.tree; + tree.setChildren(object.children); + } + + return rootChildren.toArray(new GitModelObject[rootChildren.size()]); + } + + private static class Node { + private final GitModelTree tree; + + private final List<GitModelObject> children = new ArrayList<GitModelObject>(); + + public Node(GitModelTree tree) { + this.tree = tree; + } + } +} |