View Javadoc
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 String recommendShallow;
74  	private String url;
75  	private String defaultRevision;
76  
77  	/**
78  	 * The representation of a copy file configuration.
79  	 */
80  	public static class CopyFile {
81  		final Repository repo;
82  		final String path;
83  		final String src;
84  		final String dest;
85  
86  		/**
87  		 * @param repo
88  		 *            the super project.
89  		 * @param path
90  		 *            the path of the project containing this copyfile config.
91  		 * @param src
92  		 *            the source path relative to the sub repo.
93  		 * @param dest
94  		 *            the destination path relative to the super project.
95  		 */
96  		public CopyFile(Repository repo, String path, String src, String dest) {
97  			this.repo = repo;
98  			this.path = path;
99  			this.src = src;
100 			this.dest = dest;
101 		}
102 
103 		/**
104 		 * Do the copy file action.
105 		 *
106 		 * @throws IOException
107 		 */
108 		public void copy() throws IOException {
109 			File srcFile = new File(repo.getWorkTree(),
110 					path + "/" + src); //$NON-NLS-1$
111 			File destFile = new File(repo.getWorkTree(), dest);
112 			FileInputStream input = new FileInputStream(srcFile);
113 			try {
114 				FileOutputStream output = new FileOutputStream(destFile);
115 				try {
116 					FileChannel channel = input.getChannel();
117 					output.getChannel().transferFrom(
118 							channel, 0, channel.size());
119 				} finally {
120 					output.close();
121 				}
122 			} finally {
123 				input.close();
124 			}
125 		}
126 	}
127 
128 	/**
129 	 * @param name
130 	 *            the relative path to the {@code remote}
131 	 * @param path
132 	 *            the relative path to the super project
133 	 * @param revision
134 	 *            a SHA-1 or branch name or tag name
135 	 * @param remote
136 	 *            name of the remote definition
137 	 * @param groups
138 	 *            set of groups
139 	 * @param recommendShallow
140 	 *            recommendation for shallowness
141 	 * @since 4.4
142 	 */
143 	public RepoProject(String name, String path, String revision,
144 			String remote, Set<String> groups,
145 			String recommendShallow) {
146 		if (name == null) {
147 			throw new NullPointerException();
148 		}
149 		this.name = name;
150 		if (path != null)
151 			this.path = path;
152 		else
153 			this.path = name;
154 		this.revision = revision;
155 		this.remote = remote;
156 		this.groups = groups;
157 		this.recommendShallow = recommendShallow;
158 		copyfiles = new ArrayList<CopyFile>();
159 	}
160 
161 	/**
162 	 * @param name
163 	 *            the relative path to the {@code remote}
164 	 * @param path
165 	 *            the relative path to the super project
166 	 * @param revision
167 	 *            a SHA-1 or branch name or tag name
168 	 * @param remote
169 	 *            name of the remote definition
170 	 * @param groups
171 	 *            comma separated group list
172 	 */
173 	public RepoProject(String name, String path, String revision,
174 			String remote, String groups) {
175 		this(name, path, revision, remote, new HashSet<String>(), null);
176 		if (groups != null && groups.length() > 0)
177 			this.setGroups(groups);
178 	}
179 
180 	/**
181 	 * Set the url of the sub repo.
182 	 *
183 	 * @param url
184 	 * @return this for chaining.
185 	 */
186 	public RepoProject setUrl(String url) {
187 		this.url = url;
188 		return this;
189 	}
190 
191 	/**
192 	 * Set the url of the sub repo.
193 	 *
194 	 * @param groups
195 	 *            comma separated group list
196 	 * @return this for chaining.
197 	 * @since 4.4
198 	 */
199 	public RepoProject setGroups(String groups) {
200 		this.groups.clear();
201 		this.groups.addAll(Arrays.asList(groups.split(","))); //$NON-NLS-1$
202 		return this;
203 	}
204 
205 	/**
206 	 * Set the default revision for the sub repo.
207 	 *
208 	 * @param defaultRevision
209 	 * @return this for chaining.
210 	 */
211 	public RepoProject setDefaultRevision(String defaultRevision) {
212 		this.defaultRevision = defaultRevision;
213 		return this;
214 	}
215 
216 	/**
217 	 * Get the name (relative path to the {@code remote}) of this sub repo.
218 	 *
219 	 * @return {@code name}
220 	 */
221 	public String getName() {
222 		return name;
223 	}
224 
225 	/**
226 	 * Get the path (relative path to the super project) of this sub repo.
227 	 *
228 	 * @return {@code path}
229 	 */
230 	public String getPath() {
231 		return path;
232 	}
233 
234 	/**
235 	 * Get the revision of the sub repo.
236 	 *
237 	 * @return {@code revision} if set, or {@code defaultRevision}.
238 	 */
239 	public String getRevision() {
240 		return revision == null ? defaultRevision : revision;
241 	}
242 
243 	/**
244 	 * Getter for the copyfile configurations.
245 	 *
246 	 * @return Immutable copy of {@code copyfiles}
247 	 */
248 	public List<CopyFile> getCopyFiles() {
249 		return Collections.unmodifiableList(copyfiles);
250 	}
251 
252 	/**
253 	 * Get the url of the sub repo.
254 	 *
255 	 * @return {@code url}
256 	 */
257 	public String getUrl() {
258 		return url;
259 	}
260 
261 	/**
262 	 * Get the name of the remote definition of the sub repo.
263 	 *
264 	 * @return {@code remote}
265 	 */
266 	public String getRemote() {
267 		return remote;
268 	}
269 
270 	/**
271 	 * Test whether this sub repo belongs to a specified group.
272 	 *
273 	 * @param group
274 	 * @return true if {@code group} is present.
275 	 */
276 	public boolean inGroup(String group) {
277 		return groups.contains(group);
278 	}
279 
280 	/**
281 	 * Return the set of groups.
282 	 *
283 	 * @return a Set of groups.
284 	 * @since 4.4
285 	 */
286 	public Set<String> getGroups() {
287 		return groups;
288 	}
289 
290 	/**
291 	 * Return the recommendation for shallowness.
292 	 *
293 	 * @return the String of "clone-depth"
294 	 * @since 4.4
295 	 */
296 	public String getRecommendShallow() {
297 		return recommendShallow;
298 	}
299 
300 	/**
301 	 * Sets the recommendation for shallowness.
302 	 *
303 	 * @param recommendShallow
304 	 *            recommendation for shallowness
305 	 * @since 4.4
306 	 */
307 	public void setRecommendShallow(String recommendShallow) {
308 		this.recommendShallow = recommendShallow;
309 	}
310 
311 	/**
312 	 * Add a copy file configuration.
313 	 *
314 	 * @param copyfile
315 	 */
316 	public void addCopyFile(CopyFile copyfile) {
317 		copyfiles.add(copyfile);
318 	}
319 
320 	/**
321 	 * Add a bunch of copyfile configurations.
322 	 *
323 	 * @param copyFiles
324 	 */
325 	public void addCopyFiles(Collection<CopyFile> copyFiles) {
326 		this.copyfiles.addAll(copyFiles);
327 	}
328 
329 	/**
330 	 * Clear all the copyfiles.
331 	 *
332 	 * @since 4.2
333 	 */
334 	public void clearCopyFiles() {
335 		this.copyfiles.clear();
336 	}
337 
338 	private String getPathWithSlash() {
339 		if (path.endsWith("/")) //$NON-NLS-1$
340 			return path;
341 		else
342 			return path + "/"; //$NON-NLS-1$
343 	}
344 
345 	/**
346 	 * Check if this sub repo is the ancestor of given sub repo.
347 	 *
348 	 * @param that
349 	 *            non null
350 	 * @return true if this sub repo is the ancestor of given sub repo.
351 	 */
352 	public boolean isAncestorOf(RepoProject that) {
353 		return isAncestorOf(that.getPathWithSlash());
354 	}
355 
356 	/**
357 	 * Check if this sub repo is an ancestor of the given path.
358 	 *
359 	 * @param thatPath
360 	 *            path to be checked to see if it is within this repository
361 	 * @return true if this sub repo is an ancestor of the given path.
362 	 * @since 4.2
363 	 */
364 	public boolean isAncestorOf(String thatPath) {
365 		return thatPath.startsWith(getPathWithSlash());
366 	}
367 
368 	@Override
369 	public boolean equals(Object o) {
370 		if (o instanceof RepoProject) {
371 			RepoProject that = (RepoProject) o;
372 			return this.getPathWithSlash().equals(that.getPathWithSlash());
373 		}
374 		return false;
375 	}
376 
377 	@Override
378 	public int hashCode() {
379 		return this.getPathWithSlash().hashCode();
380 	}
381 
382 	@Override
383 	public int compareTo(RepoProject that) {
384 		return this.getPathWithSlash().compareTo(that.getPathWithSlash());
385 	}
386 }
387