1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.api;
11
12 import java.io.File;
13 import java.io.IOException;
14 import java.text.MessageFormat;
15
16 import org.eclipse.jgit.api.errors.GitAPIException;
17 import org.eclipse.jgit.api.errors.JGitInternalException;
18 import org.eclipse.jgit.api.errors.NoFilepatternException;
19 import org.eclipse.jgit.errors.ConfigInvalidException;
20 import org.eclipse.jgit.internal.JGitText;
21 import org.eclipse.jgit.internal.submodule.SubmoduleValidator;
22 import org.eclipse.jgit.lib.ConfigConstants;
23 import org.eclipse.jgit.lib.Constants;
24 import org.eclipse.jgit.lib.NullProgressMonitor;
25 import org.eclipse.jgit.lib.ProgressMonitor;
26 import org.eclipse.jgit.lib.Repository;
27 import org.eclipse.jgit.lib.StoredConfig;
28 import org.eclipse.jgit.storage.file.FileBasedConfig;
29 import org.eclipse.jgit.submodule.SubmoduleWalk;
30 import org.eclipse.jgit.treewalk.filter.PathFilter;
31 import org.eclipse.jgit.treewalk.filter.TreeFilter;
32
33
34
35
36
37
38
39
40
41
42
43
44 public class SubmoduleAddCommand extends
45 TransportCommand<SubmoduleAddCommand, Repository> {
46
47 private String name;
48
49 private String path;
50
51 private String uri;
52
53 private ProgressMonitor monitor;
54
55
56
57
58
59
60
61 public SubmoduleAddCommand(Repository repo) {
62 super(repo);
63 }
64
65
66
67
68
69
70
71
72 public SubmoduleAddCommand setName(String name) {
73 this.name = name;
74 return this;
75 }
76
77
78
79
80
81
82
83
84 public SubmoduleAddCommand setPath(String path) {
85 this.path = path;
86 return this;
87 }
88
89
90
91
92
93
94
95
96 public SubmoduleAddCommand setURI(String uri) {
97 this.uri = uri;
98 return this;
99 }
100
101
102
103
104
105
106
107
108
109
110 public SubmoduleAddCommand setProgressMonitor(ProgressMonitor monitor) {
111 this.monitor = monitor;
112 return this;
113 }
114
115
116
117
118
119
120
121 protected boolean submoduleExists() throws IOException {
122 TreeFilter filter = PathFilter.create(path);
123 try (SubmoduleWalk w = SubmoduleWalk.forIndex(repo)) {
124 return w.setFilter(filter).next();
125 }
126 }
127
128
129
130
131
132
133
134
135
136
137
138 @Override
139 public Repository call() throws GitAPIException {
140 checkCallable();
141 if (path == null || path.length() == 0)
142 throw new IllegalArgumentException(JGitText.get().pathNotConfigured);
143 if (uri == null || uri.length() == 0)
144 throw new IllegalArgumentException(JGitText.get().uriNotConfigured);
145 if (name == null || name.length() == 0) {
146
147 name = path;
148 }
149
150 try {
151 SubmoduleValidator.assertValidSubmoduleName(name);
152 SubmoduleValidator.assertValidSubmodulePath(path);
153 SubmoduleValidator.assertValidSubmoduleUri(uri);
154 } catch (SubmoduleValidator.SubmoduleValidationException e) {
155 throw new IllegalArgumentException(e.getMessage());
156 }
157
158 try {
159 if (submoduleExists())
160 throw new JGitInternalException(MessageFormat.format(
161 JGitText.get().submoduleExists, path));
162 } catch (IOException e) {
163 throw new JGitInternalException(e.getMessage(), e);
164 }
165
166 final String resolvedUri;
167 try {
168 resolvedUri = SubmoduleWalk.getSubmoduleRemoteUrl(repo, uri);
169 } catch (IOException e) {
170 throw new JGitInternalException(e.getMessage(), e);
171 }
172
173 File moduleDirectory = SubmoduleWalk.getSubmoduleDirectory(repo, path);
174 CloneCommand clone = Git.cloneRepository();
175 configure(clone);
176 clone.setDirectory(moduleDirectory);
177 clone.setGitDir(new File(new File(repo.getDirectory(),
178 Constants.MODULES), path));
179 clone.setURI(resolvedUri);
180 if (monitor != null)
181 clone.setProgressMonitor(monitor);
182 Repository subRepo = null;
183 try (Git git = clone.call()) {
184 subRepo = git.getRepository();
185 subRepo.incrementOpen();
186 }
187
188
189 StoredConfig config = repo.getConfig();
190 config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, name,
191 ConfigConstants.CONFIG_KEY_URL, resolvedUri);
192 try {
193 config.save();
194 } catch (IOException e) {
195 throw new JGitInternalException(e.getMessage(), e);
196 }
197
198
199 FileBasedConfig modulesConfig = new FileBasedConfig(new File(
200 repo.getWorkTree(), Constants.DOT_GIT_MODULES), repo.getFS());
201 try {
202 modulesConfig.load();
203 modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
204 name, ConfigConstants.CONFIG_KEY_PATH, path);
205 modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
206 name, ConfigConstants.CONFIG_KEY_URL, uri);
207 modulesConfig.save();
208 } catch (IOException | ConfigInvalidException e) {
209 throw new JGitInternalException(e.getMessage(), e);
210 }
211
212 AddCommand add = new AddCommand(repo);
213
214 add.addFilepattern(Constants.DOT_GIT_MODULES);
215
216 add.addFilepattern(path);
217 try {
218 add.call();
219 } catch (NoFilepatternException e) {
220 throw new JGitInternalException(e.getMessage(), e);
221 }
222
223 return subRepo;
224 }
225 }