Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
SvnTagBranchUtils |
|
| 3.533333333333333;3,533 |
1 | package org.apache.maven.scm.provider.svn; | |
2 | ||
3 | /* | |
4 | * Licensed to the Apache Software Foundation (ASF) under one | |
5 | * or more contributor license agreements. See the NOTICE file | |
6 | * distributed with this work for additional information | |
7 | * regarding copyright ownership. The ASF licenses this file | |
8 | * to you under the Apache License, Version 2.0 (the | |
9 | * "License"); you may not use this file except in compliance | |
10 | * with the License. You may obtain a copy of the License at | |
11 | * | |
12 | * http://www.apache.org/licenses/LICENSE-2.0 | |
13 | * | |
14 | * Unless required by applicable law or agreed to in writing, | |
15 | * software distributed under the License is distributed on an | |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
17 | * KIND, either express or implied. See the License for the | |
18 | * specific language governing permissions and limitations | |
19 | * under the License. | |
20 | */ | |
21 | ||
22 | import org.apache.maven.scm.ScmBranch; | |
23 | import org.apache.maven.scm.ScmTag; | |
24 | import org.apache.maven.scm.ScmVersion; | |
25 | import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository; | |
26 | import org.codehaus.plexus.util.StringUtils; | |
27 | ||
28 | /** | |
29 | * @version $Id: SvnTagBranchUtils.java 1134992 2011-06-12 21:54:27Z godin $ | |
30 | */ | |
31 | public final class SvnTagBranchUtils | |
32 | { | |
33 | ||
34 | 0 | private SvnTagBranchUtils() { |
35 | 0 | } |
36 | ||
37 | 1 | public static final String[] REVISION_SPECIFIERS = new String[]{"HEAD", "BASE", "COMMITTED", "PREV"}; |
38 | ||
39 | public static final String SVN_TRUNK = "trunk"; | |
40 | ||
41 | public static final String SVN_BRANCHES = "branches"; | |
42 | ||
43 | public static final String SVN_TAGS = "tags"; | |
44 | ||
45 | 1 | public static final String[] SVN_BASE_DIRS = new String[]{SVN_TRUNK, SVN_BRANCHES, SVN_TAGS}; |
46 | ||
47 | /** | |
48 | * Simple helper function to concatenate two paths together with a "/". | |
49 | * Handles trailing / on basePath. | |
50 | * Returns no trailing "/" if the addlPath is null | |
51 | */ | |
52 | static String appendPath( String basePath, String addlPath ) | |
53 | { | |
54 | 397 | basePath = StringUtils.stripEnd( basePath, "/" ); |
55 | ||
56 | 397 | if ( StringUtils.isEmpty( addlPath ) ) |
57 | { | |
58 | 152 | return basePath; |
59 | } | |
60 | else | |
61 | { | |
62 | 245 | return basePath + "/" + StringUtils.stripStart( addlPath, "/" ); |
63 | } | |
64 | } | |
65 | ||
66 | /** | |
67 | * Returns the project root for the given repository url, | |
68 | * where "project root" is the root of the /trunk, /branches, /tags | |
69 | * directories | |
70 | * | |
71 | * @param repoPath Repository path/url to be searched | |
72 | * @return | |
73 | */ | |
74 | public static String getProjectRoot( String repoPath ) | |
75 | { | |
76 | 736 | for ( int i = 0; i < SVN_BASE_DIRS.length; i++ ) |
77 | { | |
78 | 586 | String base = "/" + SVN_BASE_DIRS[i]; |
79 | 586 | int pos = repoPath.lastIndexOf( base + "/" ); |
80 | 586 | if ( repoPath.endsWith( base ) ) |
81 | { | |
82 | 53 | return repoPath.substring( 0, repoPath.length() - base.length() ); |
83 | } | |
84 | 533 | else if ( pos >= 0 ) |
85 | { | |
86 | 38 | return repoPath.substring( 0, pos ); |
87 | } | |
88 | } | |
89 | ||
90 | // At this point we were unable to locate the project root of this url | |
91 | // so assume that the repository url specified is the project root | |
92 | 150 | return appendPath( repoPath, null ); |
93 | } | |
94 | ||
95 | public static String resolveTagBase( SvnScmProviderRepository repository ) | |
96 | { | |
97 | 0 | return resolveTagBase( repository.getUrl() ); |
98 | } | |
99 | ||
100 | public static String resolveTagBase( String repositoryUrl ) | |
101 | { | |
102 | 112 | return appendPath( getProjectRoot( repositoryUrl ), SVN_TAGS ); |
103 | } | |
104 | ||
105 | public static String resolveBranchBase( SvnScmProviderRepository repository ) | |
106 | { | |
107 | 0 | return resolveBranchBase( repository.getUrl() ); |
108 | } | |
109 | ||
110 | public static String resolveBranchBase( String repositoryUrl ) | |
111 | { | |
112 | 85 | return appendPath( getProjectRoot( repositoryUrl ), SVN_BRANCHES ); |
113 | } | |
114 | ||
115 | /** | |
116 | * Resolves a tag to a repository url. | |
117 | * By supplying the repository to this function (rather than calling {@link #resolveTagUrl(String,ScmTag)} | |
118 | * the resolution can use the repository's tagBase to override the default tag location. | |
119 | * | |
120 | * @param repository the repository to use as a base for tag resolution | |
121 | * @param tag tag name | |
122 | * @return | |
123 | * @see #resolveUrl(String,String,String,ScmBranch) | |
124 | */ | |
125 | public static String resolveTagUrl( SvnScmProviderRepository repository, ScmTag tag ) | |
126 | { | |
127 | 19 | return resolveUrl( repository.getUrl(), repository.getTagBase(), SVN_TAGS, tag ); |
128 | } | |
129 | ||
130 | /** | |
131 | * Resolves a tag to a repository url. | |
132 | * Will not use the {@link SvnScmProviderRepository#getTagBase()} during resolution. | |
133 | * | |
134 | * @param repositoryUrl string url for the repository | |
135 | * @param tag tag name | |
136 | * @return | |
137 | * @see #resolveUrl(String,String,String,ScmBranch) | |
138 | */ | |
139 | public static String resolveTagUrl( String repositoryUrl, ScmTag tag ) | |
140 | { | |
141 | 1 | return resolveUrl( repositoryUrl, null, SVN_TAGS, tag ); |
142 | } | |
143 | ||
144 | /** | |
145 | * Resolves a branch name to a repository url. | |
146 | * By supplying the repository to this function (rather than calling {@link #resolveBranchUrl(String,ScmBranch)} | |
147 | * the resolution can use the repository's tagBase to override the default tag location. | |
148 | * | |
149 | * @param repository the repository to use as a base for tag resolution | |
150 | * @param branch tag name | |
151 | * @return | |
152 | * @see #resolveUrl(String,String,String,ScmBranch) | |
153 | */ | |
154 | public static String resolveBranchUrl( SvnScmProviderRepository repository, ScmBranch branch ) | |
155 | { | |
156 | 9 | return resolveUrl( repository.getUrl(), repository.getBranchBase(), SVN_BRANCHES, branch ); |
157 | } | |
158 | ||
159 | /** | |
160 | * Resolves a branch name to a repository url. | |
161 | * Will not use the {@link SvnScmProviderRepository#getTagBase()} during resolution. | |
162 | * | |
163 | * @param repositoryUrl string url for the repository | |
164 | * @param branch branch name | |
165 | * @return | |
166 | * @see #resolveUrl(String,String,String,ScmBranch) | |
167 | */ | |
168 | public static String resolveBranchUrl( String repositoryUrl, ScmBranch branch ) | |
169 | { | |
170 | 0 | return resolveUrl( repositoryUrl, resolveBranchBase( repositoryUrl ), SVN_BRANCHES, branch ); |
171 | } | |
172 | ||
173 | private static String addSuffix( String baseString, String suffix ) | |
174 | { | |
175 | 22 | return ( suffix != null ) ? baseString + suffix : baseString; |
176 | } | |
177 | ||
178 | ||
179 | /** | |
180 | * Resolves a tag or branch name to a repository url.<br> | |
181 | * If the <code>branchTagName</code> is an absolute URL, that value is returned. | |
182 | * (i.e. http://foo.com/svn/myproject/tags/my-tag)<br> | |
183 | * <p/> | |
184 | * If the repository has a {@link SvnScmProviderRepository#getTagBase()} specified, | |
185 | * the tag is simply appended to the tagBase value. Note that at this time, we are using | |
186 | * the tagBase as a base for both branches and tags.<br> | |
187 | * <p/> | |
188 | * If the <code>branchTagName</code> contains a branch/tag specifier (i.e. "/branches", "/tags", "/trunk"), | |
189 | * the <code>branchTagName</code> is appended to the <code>projectRoot</code> without adding the subdir.<br> | |
190 | * Else, the result is in the format of <code>projectRoot/subdir/branchTagName</code> directory.<br> | |
191 | * | |
192 | * @param repositoryUrl string url for the repository | |
193 | * @param tagBase tagBase to use. | |
194 | * @param subdir Subdirectory to append to the project root | |
195 | * (for branching use "branches", tags use "tags") | |
196 | * @param branchTag Name of the actual branch or tag. Can be an absolute url, simple tag/branch name, | |
197 | * or even contain a relative path to the root like "branches/my-branch" | |
198 | * @return | |
199 | */ | |
200 | public static String resolveUrl( String repositoryUrl, String tagBase, String subdir, ScmBranch branchTag ) | |
201 | { | |
202 | 29 | String branchTagName = branchTag.getName(); |
203 | 29 | String projectRoot = getProjectRoot( repositoryUrl ); |
204 | 29 | branchTagName = StringUtils.strip( branchTagName, "/" ); |
205 | ||
206 | 29 | if ( StringUtils.isEmpty( branchTagName ) ) |
207 | { | |
208 | 0 | return null; |
209 | } | |
210 | ||
211 | // Look for a query string as in ViewCVS urls | |
212 | 29 | String queryString = null; |
213 | 29 | if ( repositoryUrl.indexOf( '?' ) >= 0 ) |
214 | { | |
215 | 2 | queryString = repositoryUrl.substring( repositoryUrl.indexOf( '?' ) ); |
216 | // if repositoryUrl contains a query string, remove it from repositoryUrlRoot; will be re-appended later | |
217 | 2 | projectRoot = StringUtils.replace( projectRoot, queryString, "" ); |
218 | } | |
219 | ||
220 | 29 | if ( branchTagName.indexOf( "://" ) >= 0 ) |
221 | { | |
222 | // branch/tag is already an absolute url so just return it. | |
223 | 2 | return branchTagName; |
224 | } | |
225 | ||
226 | // User has a tagBase specified so just return the name appended to the tagBase | |
227 | 27 | if ( StringUtils.isNotEmpty( tagBase ) && !tagBase.equals( resolveTagBase( repositoryUrl ) ) |
228 | && !tagBase.equals( resolveBranchBase( repositoryUrl ) ) ) | |
229 | { | |
230 | 5 | return appendPath( tagBase, branchTagName ); |
231 | } | |
232 | ||
233 | // Look for any "branches/" or "tags/" specifiers in the branchTagName. If one occurs, | |
234 | // don't append the subdir to the projectRoot when appending the name | |
235 | 80 | for ( int i = 0; i < SVN_BASE_DIRS.length; i++ ) |
236 | { | |
237 | 62 | if ( branchTagName.startsWith( SVN_BASE_DIRS[i] + "/" ) ) |
238 | { | |
239 | 4 | return addSuffix( appendPath( projectRoot, branchTagName ), queryString ); |
240 | } | |
241 | } | |
242 | ||
243 | 18 | return addSuffix( appendPath( appendPath( projectRoot, subdir ), branchTagName ), queryString ); |
244 | } | |
245 | ||
246 | /* Helper function that does the checking for {@link #isRevisionSpecifier} | |
247 | */ | |
248 | private static boolean checkRevisionArg( String arg ) | |
249 | { | |
250 | 21 | if ( StringUtils.isNumeric( arg ) || ( arg.startsWith( "{" ) && arg.endsWith( "}" ) ) ) |
251 | { | |
252 | 7 | return true; |
253 | } | |
254 | ||
255 | 48 | for ( int i = 0; i < REVISION_SPECIFIERS.length; i++ ) |
256 | { | |
257 | 42 | if ( REVISION_SPECIFIERS[i].equalsIgnoreCase( arg ) ) |
258 | { | |
259 | 8 | return true; |
260 | } | |
261 | } | |
262 | ||
263 | 6 | return false; |
264 | } | |
265 | ||
266 | /** | |
267 | * Returns whether the supplied tag refers to an actual revision or | |
268 | * is specifying a tag/branch url in the repository. | |
269 | * According to the subversion documentation, the following are valid revision specifiers: | |
270 | * NUMBER revision number | |
271 | * "{" DATE "}" revision at start of the date | |
272 | * "HEAD" latest in repository | |
273 | * "BASE" base rev of item's working copy | |
274 | * "COMMITTED" last commit at or before BASE | |
275 | * "PREV" | |
276 | * <p/> | |
277 | * For command such as diff, the revision argument can be in the format of: | |
278 | * IDENTIFIER:IDENTIFIER where IDENTIFIER is one of the args listed above | |
279 | */ | |
280 | public static boolean isRevisionSpecifier( ScmVersion version ) | |
281 | { | |
282 | 13 | if ( version == null ) |
283 | { | |
284 | 0 | return false; |
285 | } | |
286 | ||
287 | 13 | String versionName = version.getName(); |
288 | ||
289 | 13 | if ( StringUtils.isEmpty( versionName ) ) |
290 | { | |
291 | 0 | return false; |
292 | } | |
293 | ||
294 | 13 | if ( checkRevisionArg( versionName ) ) |
295 | { | |
296 | 7 | return true; |
297 | } | |
298 | ||
299 | 6 | String[] parts = StringUtils.split( versionName, ":" ); |
300 | 6 | if ( parts.length == 2 && StringUtils.isNotEmpty( parts[0] ) && StringUtils.isNotEmpty( parts[1] ) ) |
301 | { | |
302 | 4 | return checkRevisionArg( parts[0] ) && checkRevisionArg( parts[1] ); |
303 | } | |
304 | ||
305 | 2 | return false; |
306 | } | |
307 | } |