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.text.MessageFormat;
48
49 import org.eclipse.jgit.api.errors.GitAPIException;
50 import org.eclipse.jgit.api.errors.JGitInternalException;
51 import org.eclipse.jgit.api.errors.NoFilepatternException;
52 import org.eclipse.jgit.errors.ConfigInvalidException;
53 import org.eclipse.jgit.internal.JGitText;
54 import org.eclipse.jgit.internal.submodule.SubmoduleValidator;
55 import org.eclipse.jgit.lib.ConfigConstants;
56 import org.eclipse.jgit.lib.Constants;
57 import org.eclipse.jgit.lib.NullProgressMonitor;
58 import org.eclipse.jgit.lib.ProgressMonitor;
59 import org.eclipse.jgit.lib.Repository;
60 import org.eclipse.jgit.lib.StoredConfig;
61 import org.eclipse.jgit.storage.file.FileBasedConfig;
62 import org.eclipse.jgit.submodule.SubmoduleWalk;
63 import org.eclipse.jgit.treewalk.filter.PathFilter;
64 import org.eclipse.jgit.treewalk.filter.TreeFilter;
65
66
67
68
69
70
71
72
73
74
75
76
77 public class SubmoduleAddCommand extends
78 TransportCommand<SubmoduleAddCommand, Repository> {
79
80 private String name;
81
82 private String path;
83
84 private String uri;
85
86 private ProgressMonitor monitor;
87
88
89
90
91
92
93
94 public SubmoduleAddCommand(Repository repo) {
95 super(repo);
96 }
97
98
99
100
101
102
103
104
105 public SubmoduleAddCommand setName(String name) {
106 this.name = name;
107 return this;
108 }
109
110
111
112
113
114
115
116
117 public SubmoduleAddCommand setPath(String path) {
118 this.path = path;
119 return this;
120 }
121
122
123
124
125
126
127
128
129 public SubmoduleAddCommand setURI(String uri) {
130 this.uri = uri;
131 return this;
132 }
133
134
135
136
137
138
139
140
141
142
143 public SubmoduleAddCommand setProgressMonitor(ProgressMonitor monitor) {
144 this.monitor = monitor;
145 return this;
146 }
147
148
149
150
151
152
153
154 protected boolean submoduleExists() throws IOException {
155 TreeFilter filter = PathFilter.create(path);
156 try (SubmoduleWalk w = SubmoduleWalk.forIndex(repo)) {
157 return w.setFilter(filter).next();
158 }
159 }
160
161
162
163
164
165
166
167
168
169
170
171 @Override
172 public Repository call() throws GitAPIException {
173 checkCallable();
174 if (path == null || path.length() == 0)
175 throw new IllegalArgumentException(JGitText.get().pathNotConfigured);
176 if (uri == null || uri.length() == 0)
177 throw new IllegalArgumentException(JGitText.get().uriNotConfigured);
178 if (name == null || name.length() == 0) {
179
180 name = path;
181 }
182
183 try {
184 SubmoduleValidator.assertValidSubmoduleName(name);
185 SubmoduleValidator.assertValidSubmodulePath(path);
186 SubmoduleValidator.assertValidSubmoduleUri(uri);
187 } catch (SubmoduleValidator.SubmoduleValidationException e) {
188 throw new IllegalArgumentException(e.getMessage());
189 }
190
191 try {
192 if (submoduleExists())
193 throw new JGitInternalException(MessageFormat.format(
194 JGitText.get().submoduleExists, path));
195 } catch (IOException e) {
196 throw new JGitInternalException(e.getMessage(), e);
197 }
198
199 final String resolvedUri;
200 try {
201 resolvedUri = SubmoduleWalk.getSubmoduleRemoteUrl(repo, uri);
202 } catch (IOException e) {
203 throw new JGitInternalException(e.getMessage(), e);
204 }
205
206 File moduleDirectory = SubmoduleWalk.getSubmoduleDirectory(repo, path);
207 CloneCommand clone = Git.cloneRepository();
208 configure(clone);
209 clone.setDirectory(moduleDirectory);
210 clone.setGitDir(new File(new File(repo.getDirectory(),
211 Constants.MODULES), path));
212 clone.setURI(resolvedUri);
213 if (monitor != null)
214 clone.setProgressMonitor(monitor);
215 Repository subRepo = null;
216 try (Git git = clone.call()) {
217 subRepo = git.getRepository();
218 subRepo.incrementOpen();
219 }
220
221
222 StoredConfig config = repo.getConfig();
223 config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, name,
224 ConfigConstants.CONFIG_KEY_URL, resolvedUri);
225 try {
226 config.save();
227 } catch (IOException e) {
228 throw new JGitInternalException(e.getMessage(), e);
229 }
230
231
232 FileBasedConfig modulesConfig = new FileBasedConfig(new File(
233 repo.getWorkTree(), Constants.DOT_GIT_MODULES), repo.getFS());
234 try {
235 modulesConfig.load();
236 modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
237 name, ConfigConstants.CONFIG_KEY_PATH, path);
238 modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
239 name, ConfigConstants.CONFIG_KEY_URL, uri);
240 modulesConfig.save();
241 } catch (IOException e) {
242 throw new JGitInternalException(e.getMessage(), e);
243 } catch (ConfigInvalidException e) {
244 throw new JGitInternalException(e.getMessage(), e);
245 }
246
247 AddCommand add = new AddCommand(repo);
248
249 add.addFilepattern(Constants.DOT_GIT_MODULES);
250
251 add.addFilepattern(path);
252 try {
253 add.call();
254 } catch (NoFilepatternException e) {
255 throw new JGitInternalException(e.getMessage(), e);
256 }
257
258 return subRepo;
259 }
260 }