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