1 /*
2 * Copyright (C) 2015, Google Inc.
3 * and other copyright owners as documented in the project's IP log.
4 *
5 * This program and the accompanying materials are made available
6 * under the terms of the Eclipse Distribution License v1.0 which
7 * accompanies this distribution, is reproduced below, and is
8 * available at http://www.eclipse.org/org/documents/edl-v10.php
9 *
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
23 *
24 * - Neither the name of the Eclipse Foundation, Inc. nor the
25 * names of its contributors may be used to endorse or promote
26 * products derived from this software without specific prior
27 * written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43 package org.eclipse.jgit.gitrepo;
44
45 import java.io.File;
46 import java.io.FileInputStream;
47 import java.io.FileOutputStream;
48 import java.io.IOException;
49 import java.nio.channels.FileChannel;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.HashSet;
55 import java.util.List;
56 import java.util.Set;
57
58 import org.eclipse.jgit.lib.Repository;
59
60 /**
61 * The representation of a repo sub project.
62 *
63 * @see <a href="https://code.google.com/p/git-repo/">git-repo project page</a>
64 * @since 4.0
65 */
66 public class RepoProject implements Comparable<RepoProject> {
67 private final String name;
68 private final String path;
69 private final String revision;
70 private final String remote;
71 private final Set<String> groups;
72 private final List<CopyFile> copyfiles;
73 private final List<LinkFile> linkfiles;
74 private String recommendShallow;
75 private String url;
76 private String defaultRevision;
77
78 /**
79 * The representation of a reference file configuration.
80 *
81 * @since 4.8
82 */
83 public static class ReferenceFile {
84 final Repository repo;
85 final String path;
86 final String src;
87 final String dest;
88
89 /**
90 * @param repo
91 * the super project.
92 * @param path
93 * the path of the project containing this copyfile config.
94 * @param src
95 * the source path relative to the sub repo.
96 * @param dest
97 * the destination path relative to the super project.
98 */
99 public ReferenceFile(Repository repo, String path, String src, String dest) {
100 this.repo = repo;
101 this.path = path;
102 this.src = src;
103 this.dest = dest;
104 }
105 }
106
107 /**
108 * The representation of a copy file configuration.
109 */
110 public static class CopyFile extends ReferenceFile {
111 /**
112 * @param repo
113 * the super project.
114 * @param path
115 * the path of the project containing this copyfile config.
116 * @param src
117 * the source path relative to the sub repo.
118 * @param dest
119 * the destination path relative to the super project.
120 */
121 public CopyFile(Repository repo, String path, String src, String dest) {
122 super(repo, path, src, dest);
123 }
124
125 /**
126 * Do the copy file action.
127 *
128 * @throws IOException
129 */
130 public void copy() throws IOException {
131 File srcFile = new File(repo.getWorkTree(),
132 path + "/" + src); //$NON-NLS-1$
133 File destFile = new File(repo.getWorkTree(), dest);
134 try (FileInputStream input = new FileInputStream(srcFile);
135 FileOutputStream output = new FileOutputStream(destFile)) {
136 FileChannel channel = input.getChannel();
137 output.getChannel().transferFrom(channel, 0, channel.size());
138 }
139 }
140 }
141
142 /**
143 * The representation of a link file configuration.
144 *
145 * @since 4.8
146 */
147 public static class LinkFile extends ReferenceFile {
148 /**
149 * @param repo
150 * the super project.
151 * @param path
152 * the path of the project containing this linkfile config.
153 * @param src
154 * the source path relative to the sub repo.
155 * @param dest
156 * the destination path relative to the super project.
157 */
158 public LinkFile(Repository repo, String path, String src, String dest) {
159 super(repo, path, src, dest);
160 }
161 }
162
163 /**
164 * Constructor for RepoProject
165 *
166 * @param name
167 * the relative path to the {@code remote}
168 * @param path
169 * the relative path to the super project
170 * @param revision
171 * a SHA-1 or branch name or tag name
172 * @param remote
173 * name of the remote definition
174 * @param groups
175 * set of groups
176 * @param recommendShallow
177 * recommendation for shallowness
178 * @since 4.4
179 */
180 public RepoProject(String name, String path, String revision,
181 String remote, Set<String> groups,
182 String recommendShallow) {
183 if (name == null) {
184 throw new NullPointerException();
185 }
186 this.name = name;
187 if (path != null)
188 this.path = path;
189 else
190 this.path = name;
191 this.revision = revision;
192 this.remote = remote;
193 this.groups = groups;
194 this.recommendShallow = recommendShallow;
195 copyfiles = new ArrayList<>();
196 linkfiles = new ArrayList<>();
197 }
198
199 /**
200 * Constructor for RepoProject
201 *
202 * @param name
203 * the relative path to the {@code remote}
204 * @param path
205 * the relative path to the super project
206 * @param revision
207 * a SHA-1 or branch name or tag name
208 * @param remote
209 * name of the remote definition
210 * @param groupsParam
211 * comma separated group list
212 */
213 public RepoProject(String name, String path, String revision,
214 String remote, String groupsParam) {
215 this(name, path, revision, remote, new HashSet<String>(), null);
216 if (groupsParam != null && groupsParam.length() > 0)
217 this.setGroups(groupsParam);
218 }
219
220 /**
221 * Set the url of the sub repo.
222 *
223 * @param url
224 * project url
225 * @return this for chaining.
226 */
227 public RepoProject setUrl(String url) {
228 this.url = url;
229 return this;
230 }
231
232 /**
233 * Set the url of the sub repo.
234 *
235 * @param groupsParam
236 * comma separated group list
237 * @return this for chaining.
238 * @since 4.4
239 */
240 public RepoProject setGroups(String groupsParam) {
241 this.groups.clear();
242 this.groups.addAll(Arrays.asList(groupsParam.split(","))); //$NON-NLS-1$
243 return this;
244 }
245
246 /**
247 * Set the default revision for the sub repo.
248 *
249 * @param defaultRevision
250 * the name of the default revision
251 * @return this for chaining.
252 */
253 public RepoProject setDefaultRevision(String defaultRevision) {
254 this.defaultRevision = defaultRevision;
255 return this;
256 }
257
258 /**
259 * Get the name (relative path to the {@code remote}) of this sub repo.
260 *
261 * @return {@code name}
262 */
263 public String getName() {
264 return name;
265 }
266
267 /**
268 * Get the path (relative path to the super project) of this sub repo.
269 *
270 * @return {@code path}
271 */
272 public String getPath() {
273 return path;
274 }
275
276 /**
277 * Get the revision of the sub repo.
278 *
279 * @return {@code revision} if set, or {@code defaultRevision}.
280 */
281 public String getRevision() {
282 return revision == null ? defaultRevision : revision;
283 }
284
285 /**
286 * Getter for the copyfile configurations.
287 *
288 * @return Immutable copy of {@code copyfiles}
289 */
290 public List<CopyFile> getCopyFiles() {
291 return Collections.unmodifiableList(copyfiles);
292 }
293
294 /**
295 * Getter for the linkfile configurations.
296 *
297 * @return Immutable copy of {@code linkfiles}
298 * @since 4.8
299 */
300 public List<LinkFile> getLinkFiles() {
301 return Collections.unmodifiableList(linkfiles);
302 }
303
304 /**
305 * Get the url of the sub repo.
306 *
307 * @return {@code url}
308 */
309 public String getUrl() {
310 return url;
311 }
312
313 /**
314 * Get the name of the remote definition of the sub repo.
315 *
316 * @return {@code remote}
317 */
318 public String getRemote() {
319 return remote;
320 }
321
322 /**
323 * Test whether this sub repo belongs to a specified group.
324 *
325 * @param group
326 * a group
327 * @return true if {@code group} is present.
328 */
329 public boolean inGroup(String group) {
330 return groups.contains(group);
331 }
332
333 /**
334 * Return the set of groups.
335 *
336 * @return a Set of groups.
337 * @since 4.4
338 */
339 public Set<String> getGroups() {
340 return groups;
341 }
342
343 /**
344 * Return the recommendation for shallowness.
345 *
346 * @return the String of "clone-depth"
347 * @since 4.4
348 */
349 public String getRecommendShallow() {
350 return recommendShallow;
351 }
352
353 /**
354 * Sets the recommendation for shallowness.
355 *
356 * @param recommendShallow
357 * recommendation for shallowness
358 * @since 4.4
359 */
360 public void setRecommendShallow(String recommendShallow) {
361 this.recommendShallow = recommendShallow;
362 }
363
364 /**
365 * Add a copy file configuration.
366 *
367 * @param copyfile a {@link org.eclipse.jgit.gitrepo.RepoProject.CopyFile} object.
368 */
369 public void addCopyFile(CopyFile copyfile) {
370 copyfiles.add(copyfile);
371 }
372
373 /**
374 * Add a bunch of copyfile configurations.
375 *
376 * @param copyFiles
377 * a collection of
378 * {@link org.eclipse.jgit.gitrepo.RepoProject.CopyFile} objects
379 */
380 public void addCopyFiles(Collection<CopyFile> copyFiles) {
381 this.copyfiles.addAll(copyFiles);
382 }
383
384 /**
385 * Clear all the copyfiles.
386 *
387 * @since 4.2
388 */
389 public void clearCopyFiles() {
390 this.copyfiles.clear();
391 }
392
393 /**
394 * Add a link file configuration.
395 *
396 * @param linkfile a {@link org.eclipse.jgit.gitrepo.RepoProject.LinkFile} object.
397 * @since 4.8
398 */
399 public void addLinkFile(LinkFile linkfile) {
400 linkfiles.add(linkfile);
401 }
402
403 /**
404 * Add a bunch of linkfile configurations.
405 *
406 * @param linkFiles
407 * a collection of {@link LinkFile}s
408 * @since 4.8
409 */
410 public void addLinkFiles(Collection<LinkFile> linkFiles) {
411 this.linkfiles.addAll(linkFiles);
412 }
413
414 /**
415 * Clear all the linkfiles.
416 *
417 * @since 4.8
418 */
419 public void clearLinkFiles() {
420 this.linkfiles.clear();
421 }
422
423 private String getPathWithSlash() {
424 if (path.endsWith("/")) //$NON-NLS-1$
425 return path;
426 else
427 return path + "/"; //$NON-NLS-1$
428 }
429
430 /**
431 * Check if this sub repo is the ancestor of given sub repo.
432 *
433 * @param that
434 * non null
435 * @return true if this sub repo is the ancestor of given sub repo.
436 */
437 public boolean isAncestorOf(RepoProject that) {
438 return isAncestorOf(that.getPathWithSlash());
439 }
440
441 /**
442 * Check if this sub repo is an ancestor of the given path.
443 *
444 * @param thatPath
445 * path to be checked to see if it is within this repository
446 * @return true if this sub repo is an ancestor of the given path.
447 * @since 4.2
448 */
449 public boolean isAncestorOf(String thatPath) {
450 return thatPath.startsWith(getPathWithSlash());
451 }
452
453 /** {@inheritDoc} */
454 @Override
455 public boolean equals(Object o) {
456 if (o instanceof RepoProject) {
457 RepoProject that = (RepoProject) o;
458 return this.getPathWithSlash().equals(that.getPathWithSlash());
459 }
460 return false;
461 }
462
463 /** {@inheritDoc} */
464 @Override
465 public int hashCode() {
466 return this.getPathWithSlash().hashCode();
467 }
468
469 /** {@inheritDoc} */
470 @Override
471 public int compareTo(RepoProject that) {
472 return this.getPathWithSlash().compareTo(that.getPathWithSlash());
473 }
474 }
475