1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.maven.scm.provider.svn.repository;
20
21 import org.apache.maven.scm.provider.ScmProviderRepository;
22 import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
23 import org.apache.maven.scm.provider.svn.SvnTagBranchUtils;
24
25 /**
26 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
27 *
28 */
29 public class SvnScmProviderRepository extends ScmProviderRepositoryWithHost {
30 /** */
31 private String url;
32
33 private String protocol;
34
35 /**
36 * The base directory for any tags. Can be relative to the repository URL or an absolute URL.
37 */
38 private String tagBase;
39
40 /**
41 * The base directory for any branches. Can be relative to the repository URL or an absolute URL.
42 */
43 private String branchBase;
44
45 public SvnScmProviderRepository(String url) {
46 parseUrl(url);
47
48 tagBase = SvnTagBranchUtils.resolveTagBase(url);
49
50 branchBase = SvnTagBranchUtils.resolveBranchBase(url);
51 }
52
53 public SvnScmProviderRepository(String url, String user, String password) {
54 this(url);
55
56 setUser(user);
57
58 setPassword(password);
59 }
60
61 public String getUrl() {
62 return url;
63 }
64
65 /**
66 * Returns the url/directory to be used when tagging this repository.
67 */
68 public String getTagBase() {
69 return tagBase;
70 }
71
72 /**
73 * Sets the url/directory to be used when tagging this repository.
74 * The TagBase is a way to override the default tag location for the
75 * repository. The default tag location is automatically determined
76 * for repositories in the standard subversion layout (with /tags /branches /trunk).
77 * Specify this value only if the repository is using a directory other than "/tags" for tagging.
78 *
79 * @param tagBase an absolute or relative url to the base directory to create tags in.
80 * URL should be in a format that svn client understands, not the scm url format.
81 */
82 public void setTagBase(String tagBase) {
83 this.tagBase = tagBase;
84 }
85
86 /**
87 * Returns the url/directory to be used when tagging this repository.
88 */
89 public String getBranchBase() {
90 return branchBase;
91 }
92
93 /**
94 * Sets the url/directory to be used when branching this repository.
95 * The BranchBase is a way to override the default branch location for the
96 * repository. The default branch location is automatically determined
97 * for repositories in the standard subversion layout (with /tags /branches /trunk).
98 * Specify this value only if the repository is using a directory other than "/branches" for branching.
99 *
100 * @param branchBase an absolute or relative url to the base directory to create branch in.
101 * URL should be in a format that svn client understands, not the scm url format.
102 */
103 public void setBranchBase(String branchBase) {
104 this.branchBase = branchBase;
105 }
106
107 private void setProtocol(String protocol) {
108 this.protocol = protocol;
109 }
110
111 /**
112 * Get the protocol used in this repository (file://, http://, https://,...)
113 *
114 * @return the protocol
115 */
116 public String getProtocol() {
117 return protocol;
118 }
119
120 private void parseUrl(String url) {
121 if (url.startsWith("file")) {
122 setProtocol("file://");
123 } else if (url.startsWith("https")) {
124 setProtocol("https://");
125 } else if (url.startsWith("http")) {
126 setProtocol("http://");
127 } else if (url.startsWith("svn+")) {
128 setProtocol(url.substring(0, url.indexOf("://") + 3));
129 } else if (url.startsWith("svn")) {
130 setProtocol("svn://");
131 }
132
133 if (getProtocol() == null) {
134 return;
135 }
136
137 String urlPath = url.substring(getProtocol().length());
138
139 int indexAt = urlPath.indexOf('@');
140
141 // a file:// URL may contain userinfo according to RFC 8089, but our implementation is broken
142 // extract user information, broken see SCM-909
143 if (indexAt > 0 && !getProtocol().startsWith("svn+") && !getProtocol().equals("file://")) {
144 String userPassword = urlPath.substring(0, indexAt);
145 if (userPassword.indexOf(':') < 0) {
146 setUser(userPassword);
147 } else {
148 setUser(userPassword.substring(0, userPassword.indexOf(':')));
149 setPassword(userPassword.substring(userPassword.indexOf(':') + 1));
150 }
151
152 urlPath = urlPath.substring(indexAt + 1);
153
154 this.url = getProtocol() + urlPath;
155 } else {
156 this.url = getProtocol() + urlPath;
157 }
158
159 if (!"file://".equals(getProtocol())) {
160 int indexSlash = urlPath.indexOf('/');
161
162 String hostPort = urlPath;
163
164 if (indexSlash > 0) {
165 hostPort = urlPath.substring(0, indexSlash);
166 }
167
168 int indexColon = hostPort.indexOf(':');
169
170 if (indexColon > 0) {
171 setHost(hostPort.substring(0, indexColon));
172 setPort(Integer.parseInt(hostPort.substring(indexColon + 1)));
173 } else {
174 setHost(hostPort);
175 }
176 }
177 }
178
179 /** {@inheritDoc} */
180 public ScmProviderRepository getParent() {
181 String newUrl = getUrl().substring(getProtocol().length());
182
183 while (newUrl.endsWith("/.")) {
184 newUrl = newUrl.substring(0, newUrl.length() - 2);
185 }
186
187 while (newUrl.endsWith("/")) {
188 newUrl = newUrl.substring(0, newUrl.length() - 1);
189 }
190
191 int i = newUrl.lastIndexOf('/');
192
193 if (i < 0) {
194 return null;
195 }
196 newUrl = newUrl.substring(0, i);
197
198 return new SvnScmProviderRepository(getProtocol() + newUrl, getUser(), getPassword());
199 }
200
201 /** {@inheritDoc} */
202 public String getRelativePath(ScmProviderRepository ancestor) {
203 if (ancestor instanceof SvnScmProviderRepository) {
204 SvnScmProviderRepository svnAncestor = (SvnScmProviderRepository) ancestor;
205
206 String path = getUrl().replaceFirst(svnAncestor.getUrl() + "/", "");
207
208 if (!path.equals(getUrl())) {
209 return path;
210 }
211 }
212 return null;
213 }
214
215 /** {@inheritDoc} */
216 public String toString() {
217 return getUrl();
218 }
219 }