1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.api;
45
46 import java.io.File;
47 import java.io.IOException;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.List;
51
52 import org.eclipse.jgit.api.errors.CheckoutConflictException;
53 import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
54 import org.eclipse.jgit.api.errors.GitAPIException;
55 import org.eclipse.jgit.api.errors.InvalidConfigurationException;
56 import org.eclipse.jgit.api.errors.InvalidMergeHeadsException;
57 import org.eclipse.jgit.api.errors.JGitInternalException;
58 import org.eclipse.jgit.api.errors.NoHeadException;
59 import org.eclipse.jgit.api.errors.NoMessageException;
60 import org.eclipse.jgit.api.errors.RefNotFoundException;
61 import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
62 import org.eclipse.jgit.dircache.DirCacheCheckout;
63 import org.eclipse.jgit.errors.ConfigInvalidException;
64 import org.eclipse.jgit.lib.ConfigConstants;
65 import org.eclipse.jgit.lib.Constants;
66 import org.eclipse.jgit.lib.NullProgressMonitor;
67 import org.eclipse.jgit.lib.ProgressMonitor;
68 import org.eclipse.jgit.lib.RefUpdate;
69 import org.eclipse.jgit.lib.Repository;
70 import org.eclipse.jgit.merge.MergeStrategy;
71 import org.eclipse.jgit.revwalk.RevCommit;
72 import org.eclipse.jgit.revwalk.RevWalk;
73 import org.eclipse.jgit.submodule.SubmoduleWalk;
74 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
75
76
77
78
79
80
81
82
83 public class SubmoduleUpdateCommand extends
84 TransportCommand<SubmoduleUpdateCommand, Collection<String>> {
85
86 private ProgressMonitor monitor;
87
88 private final Collection<String> paths;
89
90 private MergeStrategy strategy = MergeStrategy.RECURSIVE;
91
92
93
94
95 public SubmoduleUpdateCommand(final Repository repo) {
96 super(repo);
97 paths = new ArrayList<String>();
98 }
99
100
101
102
103
104
105
106
107
108 public SubmoduleUpdateCommand setProgressMonitor(
109 final ProgressMonitor monitor) {
110 this.monitor = monitor;
111 return this;
112 }
113
114
115
116
117
118
119
120
121 public SubmoduleUpdateCommand addPath(final String path) {
122 paths.add(path);
123 return this;
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 public Collection<String> call() throws InvalidConfigurationException,
141 NoHeadException, ConcurrentRefUpdateException,
142 CheckoutConflictException, InvalidMergeHeadsException,
143 WrongRepositoryStateException, NoMessageException, NoHeadException,
144 RefNotFoundException, GitAPIException {
145 checkCallable();
146
147 try (SubmoduleWalk generator = SubmoduleWalk.forIndex(repo)) {
148 if (!paths.isEmpty())
149 generator.setFilter(PathFilterGroup.createFromStrings(paths));
150 List<String> updated = new ArrayList<String>();
151 while (generator.next()) {
152
153 if (generator.getModulesPath() == null)
154 continue;
155
156 String url = generator.getConfigUrl();
157 if (url == null)
158 continue;
159
160 Repository submoduleRepo = generator.getRepository();
161
162 if (submoduleRepo == null) {
163 CloneCommand clone = Git.cloneRepository();
164 configure(clone);
165 clone.setURI(url);
166 clone.setDirectory(generator.getDirectory());
167 clone.setGitDir(new File(new File(repo.getDirectory(),
168 Constants.MODULES), generator.getPath()));
169 if (monitor != null)
170 clone.setProgressMonitor(monitor);
171 submoduleRepo = clone.call().getRepository();
172 }
173
174 try (RevWalk walk = new RevWalk(submoduleRepo)) {
175 RevCommit commit = walk
176 .parseCommit(generator.getObjectId());
177
178 String update = generator.getConfigUpdate();
179 if (ConfigConstants.CONFIG_KEY_MERGE.equals(update)) {
180 MergeCommand merge = new MergeCommand(submoduleRepo);
181 merge.include(commit);
182 merge.setProgressMonitor(monitor);
183 merge.setStrategy(strategy);
184 merge.call();
185 } else if (ConfigConstants.CONFIG_KEY_REBASE.equals(update)) {
186 RebaseCommand rebase = new RebaseCommand(submoduleRepo);
187 rebase.setUpstream(commit);
188 rebase.setProgressMonitor(monitor);
189 rebase.setStrategy(strategy);
190 rebase.call();
191 } else {
192
193
194 DirCacheCheckout co = new DirCacheCheckout(
195 submoduleRepo, submoduleRepo.lockDirCache(),
196 commit.getTree());
197 co.setFailOnConflict(true);
198 co.checkout();
199 RefUpdate refUpdate = submoduleRepo.updateRef(
200 Constants.HEAD, true);
201 refUpdate.setNewObjectId(commit);
202 refUpdate.forceUpdate();
203 }
204 } finally {
205 submoduleRepo.close();
206 }
207 updated.add(generator.getPath());
208 }
209 return updated;
210 } catch (IOException e) {
211 throw new JGitInternalException(e.getMessage(), e);
212 } catch (ConfigInvalidException e) {
213 throw new InvalidConfigurationException(e.getMessage(), e);
214 }
215 }
216
217
218
219
220
221
222
223 public SubmoduleUpdateCommand setStrategy(MergeStrategy strategy) {
224 this.strategy = strategy;
225 return this;
226 }
227 }