1 /*******************************************************************************
2 * Copyright (C) 2013 Robin Stocker <robin@nibor.org>
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
10 *******************************************************************************/
11 package org
.eclipse
.egit
.ui
.internal
.synchronize
.model
;
13 import java
.util
.ArrayList
;
14 import java
.util
.HashMap
;
15 import java
.util
.List
;
18 import org
.eclipse
.core
.runtime
.IPath
;
19 import org
.eclipse
.core
.runtime
.Path
;
20 import org
.eclipse
.egit
.core
.synchronize
.GitCommitsModelCache
.Change
;
21 import org
.eclipse
.jgit
.lib
.Repository
;
24 * For building trees of directory and file nodes out of a flat list of changes.
29 * This interface enables creating the right instances of
30 * {@link GitModelBlob} for files.
32 interface FileModelFactory
{
34 * Creates proper instance of {@link GitModelBlob} for file nodes
39 * repository associated with file that will be created
41 * change associated with file that will be created
44 * @return instance of {@link GitModelBlob}
46 GitModelBlob
createFileModel(GitModelObjectContainer parent
,
47 Repository repo
, Change change
, IPath fullPath
);
50 * Distinguish working tree from changed/staged tree
52 * @return {@code true} when this tree is working tree, {@code false}
53 * when it is a cached tree
55 boolean isWorkingTree();
59 * Interface for creating the desired instances of {@link GitModelTree}.
61 interface TreeModelFactory
{
62 GitModelTree
createTreeModel(GitModelObjectContainer parent
,
63 IPath fullPath
, int kind
);
69 * the root node of the tree to build, which will become the
70 * parent of the first level of children
75 * @return the children of the root nodes
77 public static GitModelObject
[] build(final GitModelObjectContainer root
,
78 final Repository repo
, final Map
<String
, Change
> changes
,
79 final FileModelFactory fileFactory
,
80 final TreeModelFactory treeFactory
) {
82 if (changes
== null || changes
.isEmpty())
83 return new GitModelObject
[] {};
85 final IPath rootPath
= new Path(repo
.getWorkTree()
87 final List
<GitModelObject
> rootChildren
= new ArrayList
<>();
89 final Map
<IPath
, Node
> nodes
= new HashMap
<>();
91 for (Map
.Entry
<String
, Change
> entry
: changes
.entrySet()) {
92 String repoRelativePath
= entry
.getKey();
93 Change change
= entry
.getValue();
95 GitModelObjectContainer parent
= root
;
96 List
<GitModelObject
> children
= rootChildren
;
97 IPath path
= rootPath
;
99 String
[] segments
= repoRelativePath
.split("/"); //$NON-NLS-1$
101 for (int i
= 0; i
< segments
.length
; i
++) {
102 path
= path
.append(segments
[i
]);
104 // Changes represent files, so the last segment is the file name
105 boolean fileNode
= (i
== segments
.length
- 1);
107 Node node
= nodes
.get(path
);
109 GitModelTree tree
= treeFactory
.createTreeModel(parent
,
110 path
, change
.getKind());
111 node
= new Node(tree
);
112 nodes
.put(path
, node
);
116 children
= node
.children
;
118 GitModelBlob file
= fileFactory
.createFileModel(parent
,
125 for (Node object
: nodes
.values()) {
126 GitModelTree tree
= object
.tree
;
127 tree
.setChildren(object
.children
);
130 return rootChildren
.toArray(new GitModelObject
[0]);
133 private static class Node
{
134 private final GitModelTree tree
;
136 private final List
<GitModelObject
> children
= new ArrayList
<>();
138 public Node(GitModelTree tree
) {