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