Mercurial > hg > mercurial
annotate mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java @ 169:6105c009955e
By default - use compressed transfer - as before
author | Dmitry Neverov <dmitry.neverov@jetbrains.com> |
---|---|
date | Wed, 09 Feb 2011 13:50:58 +0300 |
parents | 5198b02fc5e9 |
children | c3157374a356 |
rev | line source |
---|---|
25 | 1 /* |
160
5198b02fc5e9
Update copyrights
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
157
diff
changeset
|
2 * Copyright 2000-2011 JetBrains s.r.o. |
25 | 3 * |
4 * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 * you may not use this file except in compliance with the License. | |
6 * You may obtain a copy of the License at | |
7 * | |
8 * http://www.apache.org/licenses/LICENSE-2.0 | |
9 * | |
10 * Unless required by applicable law or agreed to in writing, software | |
11 * distributed under the License is distributed on an "AS IS" BASIS, | |
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 * See the License for the specific language governing permissions and | |
14 * limitations under the License. | |
15 */ | |
0 | 16 package jetbrains.buildServer.buildTriggers.vcs.mercurial; |
17 | |
103 | 18 import jetbrains.buildServer.BuildAgent; |
0 | 19 import jetbrains.buildServer.Used; |
20 import jetbrains.buildServer.buildTriggers.vcs.AbstractVcsPropertiesProcessor; | |
21 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*; | |
22 import jetbrains.buildServer.log.Loggers; | |
103 | 23 import jetbrains.buildServer.serverSide.*; |
24 import jetbrains.buildServer.util.EventDispatcher; | |
0 | 25 import jetbrains.buildServer.util.FileUtil; |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
26 import jetbrains.buildServer.util.StringUtil; |
103 | 27 import jetbrains.buildServer.util.filters.Filter; |
28 import jetbrains.buildServer.util.filters.FilterUtil; | |
0 | 29 import jetbrains.buildServer.vcs.*; |
30 import jetbrains.buildServer.vcs.patches.PatchBuilder; | |
31 import org.jetbrains.annotations.NotNull; | |
32 import org.jetbrains.annotations.Nullable; | |
33 | |
1 | 34 import java.io.File; |
35 import java.io.FileFilter; | |
36 import java.io.FileInputStream; | |
37 import java.io.IOException; | |
38 import java.util.*; | |
21 | 39 import java.util.concurrent.ConcurrentHashMap; |
40 import java.util.concurrent.ConcurrentMap; | |
41 import java.util.concurrent.locks.Lock; | |
42 import java.util.concurrent.locks.ReentrantLock; | |
1 | 43 |
19 | 44 /** |
45 * Mercurial VCS plugin for TeamCity works as follows: | |
46 * <ul> | |
47 * <li>clones repository to internal storage | |
48 * <li>before any operation with working copy of repository pulls changes from the original repository | |
49 * <li>executes corresponding hg command | |
50 * </ul> | |
51 * | |
57 | 52 * <p>Working copy of repository is created in the $TEAMCITY_DATA_PATH/system/caches/hg_<hash code> folder. |
19 | 53 * <p>Personal builds (remote runs) are not yet supported, they require corresponding functionality from the IDE. |
54 */ | |
148
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
55 public class MercurialVcsSupport extends ServerVcsSupport implements LabelingSupport, VcsFileContentProvider, BranchSupport { |
21 | 56 private ConcurrentMap<String, Lock> myWorkDirLocks= new ConcurrentHashMap<String, Lock>(); |
57 private VcsManager myVcsManager; | |
27
7944e8985ebd
prepare modules structure for agent side checkout
Pavel.Sher
parents:
25
diff
changeset
|
58 private File myDefaultWorkFolderParent; |
0 | 59 |
21 | 60 public MercurialVcsSupport(@NotNull final VcsManager vcsManager, |
61 @NotNull ServerPaths paths, | |
103 | 62 @NotNull final SBuildServer server, |
63 @NotNull EventDispatcher<BuildServerListener> dispatcher) { | |
21 | 64 myVcsManager = vcsManager; |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
65 myDefaultWorkFolderParent = new File(paths.getCachesDir(), "mercurial"); |
103 | 66 dispatcher.addListener(new BuildServerAdapter() { |
67 @Override | |
121 | 68 public void cleanupFinished() { |
69 super.cleanupFinished(); | |
70 server.getExecutor().submit(new Runnable() { | |
71 public void run() { | |
72 removeOldWorkFolders(); | |
73 } | |
74 }); | |
75 } | |
76 | |
77 @Override | |
103 | 78 public void sourcesVersionReleased(@NotNull final BuildAgent agent) { |
79 super.sourcesVersionReleased(agent); | |
80 server.getExecutor().submit(new Runnable() { | |
81 public void run() { | |
82 Set<File> clonedRepos = getAllClonedRepos(); | |
83 if (clonedRepos == null) return; | |
84 for (File f: clonedRepos) { | |
85 lockWorkDir(f); | |
86 try { | |
87 FileUtil.delete(f); | |
88 } finally { | |
89 unlockWorkDir(f); | |
90 } | |
91 } | |
92 } | |
93 }); | |
94 } | |
95 }); | |
0 | 96 } |
97 | |
90 | 98 private Collection<ModifiedFile> computeModifiedFilesForMergeCommit(final Settings settings, final ChangeSet cur) throws VcsException { |
99 ChangedFilesCommand cfc = new ChangedFilesCommand(settings); | |
100 cfc.setRevId(cur.getId()); | |
101 return cfc.execute(); | |
102 } | |
103 | |
145
3a8af53dea6b
Normilize file separators and map paths when collect changes
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
104 private List<VcsChange> toVcsChanges(final List<ModifiedFile> modifiedFiles, String prevVer, String curVer, CheckoutRules rules) { |
0 | 105 List<VcsChange> files = new ArrayList<VcsChange>(); |
106 for (ModifiedFile mf: modifiedFiles) { | |
145
3a8af53dea6b
Normilize file separators and map paths when collect changes
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
107 String normalizedPath = PathUtil.normalizeSeparator(mf.getPath()); |
0 | 108 VcsChangeInfo.Type changeType = getChangeType(mf.getStatus()); |
109 if (changeType == null) { | |
110 Loggers.VCS.warn("Unable to convert status: " + mf.getStatus() + " to VCS change type"); | |
111 changeType = VcsChangeInfo.Type.NOT_CHANGED; | |
112 } | |
145
3a8af53dea6b
Normilize file separators and map paths when collect changes
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
113 files.add(new VcsChange(changeType, mf.getStatus().getName(), normalizedPath, rules.map(mf.getPath()), prevVer, curVer)); |
0 | 114 } |
115 return files; | |
116 } | |
117 | |
118 private VcsChangeInfo.Type getChangeType(final ModifiedFile.Status status) { | |
119 switch (status) { | |
120 case ADDED:return VcsChangeInfo.Type.ADDED; | |
121 case MODIFIED:return VcsChangeInfo.Type.CHANGED; | |
122 case REMOVED:return VcsChangeInfo.Type.REMOVED; | |
123 } | |
124 return null; | |
125 } | |
126 | |
127 @NotNull | |
86 | 128 public byte[] getContent(@NotNull final VcsModification vcsModification, |
129 @NotNull final VcsChangeInfo change, | |
130 @NotNull final VcsChangeInfo.ContentType contentType, | |
131 @NotNull final VcsRoot vcsRoot) throws VcsException { | |
44 | 132 syncClonedRepository(vcsRoot); |
12 | 133 String version = contentType == VcsChangeInfo.ContentType.AFTER_CHANGE ? change.getAfterChangeRevisionNumber() : change.getBeforeChangeRevisionNumber(); |
134 return getContent(change.getRelativeFileName(), vcsRoot, version); | |
0 | 135 } |
136 | |
137 @NotNull | |
86 | 138 public byte[] getContent(@NotNull final String filePath, @NotNull final VcsRoot vcsRoot, @NotNull final String version) throws VcsException { |
44 | 139 syncClonedRepository(vcsRoot); |
140 Settings settings = createSettings(vcsRoot); | |
12 | 141 CatCommand cc = new CatCommand(settings); |
59
30cc10fe9479
accept version in two formats: with rev number and without
Pavel.Sher
parents:
58
diff
changeset
|
142 cc.setRevId(new ChangeSet(version).getId()); |
12 | 143 File parentDir = cc.execute(Collections.singletonList(filePath)); |
30 | 144 try { |
145 File file = new File(parentDir, filePath); | |
146 if (file.isFile()) { | |
147 try { | |
148 return FileUtil.loadFileBytes(file); | |
149 } catch (IOException e) { | |
150 throw new VcsException("Failed to load content of file: " + file.getAbsolutePath(), e); | |
151 } | |
152 } else { | |
153 Loggers.VCS.warn("Unable to obtain content of the file: " + filePath); | |
12 | 154 } |
30 | 155 } finally { |
118
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
156 deleteTmpDir(parentDir); |
12 | 157 } |
0 | 158 return new byte[0]; |
159 } | |
160 | |
86 | 161 @NotNull |
0 | 162 public String getName() { |
28
a7cab5083ada
libraries moved on top level, dummy implementation of agent side checkout interface
Pavel.Sher
parents:
27
diff
changeset
|
163 return Constants.VCS_NAME; |
0 | 164 } |
165 | |
86 | 166 @NotNull |
0 | 167 @Used("jsp") |
168 public String getDisplayName() { | |
169 return "Mercurial"; | |
170 } | |
171 | |
172 @Nullable | |
173 public PropertiesProcessor getVcsPropertiesProcessor() { | |
174 return new AbstractVcsPropertiesProcessor() { | |
175 public Collection<InvalidProperty> process(final Map<String, String> properties) { | |
176 List<InvalidProperty> result = new ArrayList<InvalidProperty>(); | |
177 if (isEmpty(properties.get(Constants.HG_COMMAND_PATH_PROP))) { | |
178 result.add(new InvalidProperty(Constants.HG_COMMAND_PATH_PROP, "Path to 'hg' command must be specified")); | |
179 } | |
180 if (isEmpty(properties.get(Constants.REPOSITORY_PROP))) { | |
181 result.add(new InvalidProperty(Constants.REPOSITORY_PROP, "Repository must be specified")); | |
182 } | |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
183 if (isEmpty(properties.get(Constants.SERVER_CLONE_PATH_PROP))) { |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
184 properties.put(Constants.SERVER_CLONE_PATH_PROP, myDefaultWorkFolderParent.getAbsolutePath()); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
185 } |
0 | 186 return result; |
187 } | |
188 }; | |
189 } | |
190 | |
86 | 191 @NotNull |
0 | 192 public String getVcsSettingsJspFilePath() { |
193 return "mercurialSettings.jsp"; | |
194 } | |
195 | |
196 @NotNull | |
86 | 197 public String getCurrentVersion(@NotNull final VcsRoot root) throws VcsException { |
19 | 198 // we will return full version of the most recent change as current version |
44 | 199 syncClonedRepository(root); |
200 Settings settings = createSettings(root); | |
57 | 201 BranchesCommand branches = new BranchesCommand(settings); |
202 Map<String, ChangeSet> result = branches.execute(); | |
203 if (!result.containsKey(settings.getBranchName())) { | |
204 throw new VcsException("Unable to find current version for the branch: " + settings.getBranchName()); | |
205 } | |
206 | |
207 return result.get(settings.getBranchName()).getFullVersion(); | |
0 | 208 } |
209 | |
106 | 210 public boolean sourcesUpdatePossibleIfChangesNotFound(@NotNull final VcsRoot root) { |
211 return false; | |
212 } | |
213 | |
86 | 214 @NotNull |
0 | 215 public String describeVcsRoot(final VcsRoot vcsRoot) { |
216 return "mercurial: " + vcsRoot.getProperty(Constants.REPOSITORY_PROP); | |
217 } | |
218 | |
106 | 219 @Override |
220 public TestConnectionSupport getTestConnectionSupport() { | |
221 return new TestConnectionSupport() { | |
222 public String testConnection(@NotNull final VcsRoot vcsRoot) throws VcsException { | |
223 Settings settings = createSettings(vcsRoot); | |
224 IdentifyCommand id = new IdentifyCommand(settings); | |
225 StringBuilder res = new StringBuilder(); | |
226 res.append(quoteIfNeeded(settings.getHgCommandPath())); | |
227 res.append(" identify "); | |
228 final String obfuscatedUrl = CommandUtil.removePrivateData(settings.getRepositoryUrl(), Collections.singleton(settings.getPassword())); | |
229 res.append(quoteIfNeeded(obfuscatedUrl)); | |
230 res.append('\n').append(id.execute()); | |
231 return res.toString(); | |
232 } | |
233 }; | |
0 | 234 } |
235 | |
17 | 236 private String quoteIfNeeded(@NotNull String str) { |
237 if (str.indexOf(' ') != -1) { | |
238 return "\"" + str + "\""; | |
239 } | |
240 | |
241 return str; | |
242 } | |
243 | |
0 | 244 @Nullable |
245 public Map<String, String> getDefaultVcsProperties() { | |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
246 Map<String, String> defaults = new HashMap<String, String>(); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
247 defaults.put(Constants.HG_COMMAND_PATH_PROP, "hg"); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
248 defaults.put(Constants.SERVER_CLONE_PATH_PROP, myDefaultWorkFolderParent.getAbsolutePath()); |
169
6105c009955e
By default - use compressed transfer - as before
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
160
diff
changeset
|
249 defaults.put(Constants.UNCOMPRESSED_TRANSFER, "false"); |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
250 return defaults; |
0 | 251 } |
252 | |
86 | 253 public String getVersionDisplayName(@NotNull final String version, @NotNull final VcsRoot root) throws VcsException { |
59
30cc10fe9479
accept version in two formats: with rev number and without
Pavel.Sher
parents:
58
diff
changeset
|
254 return new ChangeSet(version).getId(); |
0 | 255 } |
256 | |
257 @NotNull | |
258 public Comparator<String> getVersionComparator() { | |
19 | 259 // comparator is called when TeamCity needs to sort modifications in the order of their appearance, |
260 // currently we sort changes by revision number, not sure however that this is a good idea, | |
261 // probably it would be better to sort them by timestamp (and to add timestamp into the version). | |
0 | 262 return new Comparator<String>() { |
263 public int compare(final String o1, final String o2) { | |
264 try { | |
265 return new ChangeSet(o1).getRevNumber() - new ChangeSet(o2).getRevNumber(); | |
266 } catch (Exception e) { | |
267 return 1; | |
268 } | |
269 } | |
270 }; | |
271 } | |
272 | |
19 | 273 // builds patch from version to version |
79 | 274 private void buildIncrementalPatch(final Settings settings, @NotNull final ChangeSet fromVer, @NotNull final ChangeSet toVer, final PatchBuilder builder, final CheckoutRules checkoutRules) |
0 | 275 throws VcsException, IOException { |
276 StatusCommand st = new StatusCommand(settings); | |
277 st.setFromRevId(fromVer.getId()); | |
278 st.setToRevId(toVer.getId()); | |
279 List<ModifiedFile> modifiedFiles = st.execute(); | |
280 List<String> notDeletedFiles = new ArrayList<String>(); | |
281 for (ModifiedFile f: modifiedFiles) { | |
282 if (f.getStatus() != ModifiedFile.Status.REMOVED) { | |
283 notDeletedFiles.add(f.getPath()); | |
284 } | |
285 } | |
286 | |
47
c785bc4c5f39
minor fix: do not call cat command if there are no files to export
Pavel.Sher
parents:
46
diff
changeset
|
287 if (notDeletedFiles.isEmpty()) return; |
c785bc4c5f39
minor fix: do not call cat command if there are no files to export
Pavel.Sher
parents:
46
diff
changeset
|
288 |
0 | 289 CatCommand cc = new CatCommand(settings); |
290 cc.setRevId(toVer.getId()); | |
291 File parentDir = cc.execute(notDeletedFiles); | |
292 | |
293 try { | |
294 for (ModifiedFile f: modifiedFiles) { | |
79 | 295 String mappedPath = checkoutRules.map(f.getPath()); |
296 if (mappedPath == null) continue; // skip | |
297 final File virtualFile = new File(mappedPath); | |
0 | 298 if (f.getStatus() == ModifiedFile.Status.REMOVED) { |
299 builder.deleteFile(virtualFile, true); | |
300 } else { | |
301 File realFile = new File(parentDir, f.getPath()); | |
302 FileInputStream is = new FileInputStream(realFile); | |
303 try { | |
11 | 304 builder.changeOrCreateBinaryFile(virtualFile, null, is, realFile.length()); |
0 | 305 } finally { |
306 is.close(); | |
307 } | |
308 } | |
309 } | |
310 } finally { | |
118
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
311 deleteTmpDir(parentDir); |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
312 } |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
313 } |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
314 |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
315 private void deleteTmpDir(File parentDir) { |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
316 boolean dirDeleted = FileUtil.delete(parentDir); |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
317 if (!dirDeleted) { |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
318 Loggers.VCS.warn("Can not delete directory \"" + parentDir.getAbsolutePath() + "\""); |
0 | 319 } |
320 } | |
321 | |
19 | 322 // builds patch by exporting files using specified version |
79 | 323 private void buildFullPatch(final Settings settings, @NotNull final ChangeSet toVer, final PatchBuilder builder, final CheckoutRules checkoutRules) |
0 | 324 throws IOException, VcsException { |
325 CloneCommand cl = new CloneCommand(settings); | |
57 | 326 // clone from the local repository |
67
e6971dc6b17c
always use url with credentials if username/password are specified
Pavel.Sher
parents:
62
diff
changeset
|
327 cl.setRepository(settings.getLocalRepositoryDir().getAbsolutePath()); |
0 | 328 cl.setToId(toVer.getId()); |
57 | 329 cl.setUpdateWorkingDir(false); |
0 | 330 File tempDir = FileUtil.createTempDirectory("mercurial", toVer.getId()); |
331 try { | |
332 final File repRoot = new File(tempDir, "rep"); | |
333 cl.setDestDir(repRoot.getAbsolutePath()); | |
334 cl.execute(); | |
57 | 335 |
336 UpdateCommand up = new UpdateCommand(settings); | |
337 up.setWorkDirectory(repRoot.getAbsolutePath()); | |
338 up.setToId(toVer.getId()); | |
339 up.execute(); | |
340 | |
0 | 341 buildPatchFromDirectory(builder, repRoot, new FileFilter() { |
342 public boolean accept(final File file) { | |
343 return !(file.isDirectory() && ".hg".equals(file.getName())); | |
344 } | |
79 | 345 }, checkoutRules); |
0 | 346 } finally { |
347 FileUtil.delete(tempDir); | |
348 } | |
349 } | |
350 | |
79 | 351 private void buildPatchFromDirectory(final PatchBuilder builder, final File repRoot, final FileFilter filter, final CheckoutRules checkoutRules) throws IOException { |
352 buildPatchFromDirectory(repRoot, builder, repRoot, filter, checkoutRules); | |
0 | 353 } |
354 | |
79 | 355 private void buildPatchFromDirectory(File curDir, final PatchBuilder builder, final File repRoot, final FileFilter filter, final CheckoutRules checkoutRules) throws IOException { |
0 | 356 File[] files = curDir.listFiles(filter); |
357 if (files != null) { | |
358 for (File realFile: files) { | |
359 String relPath = realFile.getAbsolutePath().substring(repRoot.getAbsolutePath().length()); | |
79 | 360 String mappedPath = checkoutRules.map(relPath); |
97 | 361 if (mappedPath != null && mappedPath.length() > 0) { |
79 | 362 final File virtualFile = new File(mappedPath); |
363 if (realFile.isDirectory()) { | |
364 builder.createDirectory(virtualFile); | |
365 buildPatchFromDirectory(realFile, builder, repRoot, filter, checkoutRules); | |
366 } else { | |
367 final FileInputStream is = new FileInputStream(realFile); | |
368 try { | |
369 builder.createBinaryFile(virtualFile, null, is, realFile.length()); | |
370 } finally { | |
371 is.close(); | |
372 } | |
0 | 373 } |
97 | 374 } else { |
375 if (realFile.isDirectory()) { | |
376 buildPatchFromDirectory(realFile, builder, repRoot, filter, checkoutRules); | |
377 } | |
0 | 378 } |
379 } | |
380 } | |
381 } | |
382 | |
19 | 383 // updates current working copy of repository by pulling changes from the repository specified in VCS root |
44 | 384 private void syncClonedRepository(final VcsRoot root) throws VcsException { |
385 Settings settings = createSettings(root); | |
57 | 386 File workDir = settings.getLocalRepositoryDir(); |
21 | 387 lockWorkDir(workDir); |
388 try { | |
29 | 389 if (settings.hasCopyOfRepository()) { |
0 | 390 // update |
8 | 391 PullCommand pull = new PullCommand(settings); |
392 pull.execute(); | |
0 | 393 } else { |
394 // clone | |
395 CloneCommand cl = new CloneCommand(settings); | |
22 | 396 cl.setDestDir(workDir.getAbsolutePath()); |
18 | 397 cl.setUpdateWorkingDir(false); |
0 | 398 cl.execute(); |
399 } | |
21 | 400 } finally { |
401 unlockWorkDir(workDir); | |
0 | 402 } |
403 } | |
404 | |
44 | 405 @Override |
406 public LabelingSupport getLabelingSupport() { | |
407 return this; | |
408 } | |
409 | |
106 | 410 @NotNull |
411 public VcsFileContentProvider getContentProvider() { | |
412 return this; | |
413 } | |
414 | |
156
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
415 @NotNull |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
416 public String getRemoteRunOnBranchPattern() { |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
417 return "remote-run/{teamcity.user}/.+"; |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
418 } |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
419 |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
420 @NotNull |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
421 public Map<String, String> getBranchesRevisions(@NotNull VcsRoot root) throws VcsException { |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
422 syncClonedRepository(root); |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
423 Settings settings = createSettings(root); |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
424 BranchesCommand branches = new BranchesCommand(settings); |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
425 Map<String, String> result = new HashMap<String, String>(); |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
426 for (Map.Entry<String, ChangeSet> entry : branches.execute().entrySet()) { |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
427 result.put(entry.getKey(), entry.getValue().getId()); |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
428 } |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
429 return result; |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
430 } |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
431 |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
432 @NotNull |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
433 public Map<String, String> getBranchRootOptions(@NotNull VcsRoot root, @NotNull String branchName) { |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
434 final Map<String, String> options = new HashMap<String, String>(root.getProperties()); |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
435 options.put(Constants.BRANCH_NAME_PROP, branchName); |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
436 return options; |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
437 } |
7e36394a9c00
Implement new methods from BranchSupport
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
155
diff
changeset
|
438 |
148
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
439 public List<ModificationData> collectChanges(@NotNull VcsRoot fromRoot, @NotNull String fromRootRevision, |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
440 @NotNull VcsRoot toRoot, @Nullable String toRootRevision, |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
441 @NotNull CheckoutRules checkoutRules) throws VcsException { |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
442 //we get all branches while clone, if vcs roots are related it is doesn't matter in which one search for branch point |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
443 syncClonedRepository(fromRoot); |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
444 String branchPoint = getBranchPoint(fromRoot, fromRootRevision, toRootRevision); |
155
b71e3e8fc990
We should collect changes in the 'toRoot'
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
151
diff
changeset
|
445 return ((CollectChangesByCheckoutRules) getCollectChangesPolicy()).collectChanges(toRoot, branchPoint, toRootRevision, checkoutRules); |
148
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
446 } |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
447 |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
448 private String getBranchPoint(@NotNull VcsRoot root, String branchOneRev, String branchTwoRev) throws VcsException { |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
449 Settings settings = createSettings(root); |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
450 LogCommand lc = new LogCommand(settings); |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
451 lc.setFromRevId(new ChangeSetRevision(branchOneRev).getId()); |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
452 lc.setToRevId(new ChangeSetRevision(branchTwoRev).getId()); |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
453 lc.setLimit(1); |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
454 List<ChangeSet> changeSets = lc.execute(); |
151
97da90dac992
If branch point is initial cset - do no try to find its parents
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
148
diff
changeset
|
455 ChangeSet cs = changeSets.get(0); |
97da90dac992
If branch point is initial cset - do no try to find its parents
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
148
diff
changeset
|
456 if (cs.isInitial()) { |
97da90dac992
If branch point is initial cset - do no try to find its parents
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
148
diff
changeset
|
457 return cs.getId(); |
97da90dac992
If branch point is initial cset - do no try to find its parents
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
148
diff
changeset
|
458 } else { |
97da90dac992
If branch point is initial cset - do no try to find its parents
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
148
diff
changeset
|
459 return cs.getParents().get(0).getId(); |
97da90dac992
If branch point is initial cset - do no try to find its parents
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
148
diff
changeset
|
460 } |
148
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
461 } |
403d16397f5c
Initial implementation of BranchSupport interface
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
462 |
106 | 463 @NotNull |
464 public CollectChangesPolicy getCollectChangesPolicy() { | |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
465 return new CollectChangesByCheckoutRules() { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
466 public List<ModificationData> collectChanges(@NotNull VcsRoot root, @NotNull String fromVersion, @Nullable String currentVersion, @NotNull CheckoutRules checkoutRules) throws VcsException { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
467 syncClonedRepository(root); |
106 | 468 |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
469 // first obtain changes between specified versions |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
470 List<ModificationData> result = new ArrayList<ModificationData>(); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
471 if (currentVersion == null) return result; |
106 | 472 |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
473 Settings settings = createSettings(root); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
474 LogCommand lc = new LogCommand(settings); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
475 String fromId = new ChangeSetRevision(fromVersion).getId(); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
476 lc.setFromRevId(fromId); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
477 lc.setToRevId(new ChangeSetRevision(currentVersion).getId()); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
478 List<ChangeSet> changeSets = lc.execute(); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
479 if (changeSets.isEmpty()) { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
480 return result; |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
481 } |
106 | 482 |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
483 // invoke status command for each changeset and determine what files were modified in these changesets |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
484 StatusCommand st = new StatusCommand(settings); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
485 ChangeSet prev = new ChangeSet(fromVersion); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
486 for (ChangeSet cur : changeSets) { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
487 if (cur.getId().equals(fromId)) continue; // skip already reported changeset |
106 | 488 |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
489 String prevId = prev.getId(); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
490 List<ChangeSetRevision> curParents = cur.getParents(); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
491 boolean merge = curParents != null && curParents.size() > 1; |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
492 if (curParents != null && !merge) { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
493 prevId = curParents.get(0).getId(); |
106 | 494 } |
495 | |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
496 List<ModifiedFile> modifiedFiles = new ArrayList<ModifiedFile>(); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
497 if (merge) { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
498 modifiedFiles.addAll(computeModifiedFilesForMergeCommit(settings, cur)); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
499 } else { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
500 st.setFromRevId(prevId); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
501 st.setToRevId(cur.getId()); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
502 modifiedFiles = st.execute(); |
106 | 503 } |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
504 |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
505 // changeset full version will be set into VcsChange structure and |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
506 // stored in database (note that getContent method will be invoked with this version) |
145
3a8af53dea6b
Normilize file separators and map paths when collect changes
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
144
diff
changeset
|
507 List<VcsChange> files = toVcsChanges(modifiedFiles, prev.getFullVersion(), cur.getFullVersion(), checkoutRules); |
144
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
508 if (files.isEmpty() && !merge) continue; |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
509 ModificationData md = new ModificationData(cur.getTimestamp(), files, cur.getDescription(), cur.getUser(), root, cur.getFullVersion(), cur.getId()); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
510 if (merge) { |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
511 md.setCanBeIgnored(false); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
512 } |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
513 result.add(md); |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
514 prev = cur; |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
515 } |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
516 |
2e90ef872b68
Collect changes using CheckoutRules.
Dmitry Neverov <dmitry.neverov@jetbrains.com>
parents:
142
diff
changeset
|
517 return result; |
106 | 518 } |
519 }; | |
520 } | |
521 | |
522 @NotNull | |
523 public BuildPatchPolicy getBuildPatchPolicy() { | |
524 return new BuildPatchByCheckoutRules() { | |
525 public void buildPatch(@NotNull final VcsRoot root, | |
526 @Nullable final String fromVersion, | |
527 @NotNull final String toVersion, | |
528 @NotNull final PatchBuilder builder, | |
529 @NotNull final CheckoutRules checkoutRules) throws IOException, VcsException { | |
530 syncClonedRepository(root); | |
531 Settings settings = createSettings(root); | |
532 if (fromVersion == null) { | |
533 buildFullPatch(settings, new ChangeSet(toVersion), builder, checkoutRules); | |
534 } else { | |
535 buildIncrementalPatch(settings, new ChangeSet(fromVersion), new ChangeSet(toVersion), builder, checkoutRules); | |
536 } | |
537 } | |
538 }; | |
539 } | |
540 | |
22 | 541 private void lockWorkDir(@NotNull File workDir) { |
21 | 542 getWorkDirLock(workDir).lock(); |
543 } | |
544 | |
22 | 545 private void unlockWorkDir(@NotNull File workDir) { |
21 | 546 getWorkDirLock(workDir).unlock(); |
547 } | |
548 | |
31 | 549 @Override |
106 | 550 public boolean allowSourceCaching() { |
31 | 551 // since a copy of repository for each VCS root is already stored on disk |
106 | 552 // we do not need separate cache for our patches |
553 return false; | |
31 | 554 } |
555 | |
22 | 556 private Lock getWorkDirLock(final File workDir) { |
557 String path = workDir.getAbsolutePath(); | |
558 Lock lock = myWorkDirLocks.get(path); | |
21 | 559 if (lock == null) { |
560 lock = new ReentrantLock(); | |
22 | 561 Lock curLock = myWorkDirLocks.putIfAbsent(path, lock); |
21 | 562 if (curLock != null) { |
563 lock = curLock; | |
564 } | |
565 } | |
566 return lock; | |
567 } | |
568 | |
23 | 569 private void removeOldWorkFolders() { |
103 | 570 Set<File> workDirs = getAllClonedRepos(); |
571 if (workDirs == null) return; | |
572 | |
573 for (VcsRoot vcsRoot: getMercurialVcsRoots()) { | |
574 try { | |
575 Settings s = createSettings(vcsRoot); | |
576 workDirs.remove(PathUtil.getCanonicalFile(s.getLocalRepositoryDir())); | |
577 } catch (VcsException e) { | |
578 Loggers.VCS.error(e); | |
579 } | |
580 } | |
581 | |
582 for (File f: workDirs) { | |
583 lockWorkDir(f); | |
584 try { | |
585 FileUtil.delete(f); | |
586 } finally { | |
587 unlockWorkDir(f); | |
588 } | |
589 } | |
590 } | |
591 | |
592 private Collection<VcsRoot> getMercurialVcsRoots() { | |
593 List<VcsRoot> res = new ArrayList<VcsRoot>(myVcsManager.getAllRegisteredVcsRoots()); | |
594 FilterUtil.filterCollection(res, new Filter<VcsRoot>() { | |
595 public boolean accept(@NotNull final VcsRoot data) { | |
596 return getName().equals(data.getVcsName()); | |
597 } | |
598 }); | |
599 return res; | |
600 } | |
601 | |
602 @Nullable | |
603 private Set<File> getAllClonedRepos() { | |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
604 File workFoldersParent = myDefaultWorkFolderParent; |
103 | 605 if (!workFoldersParent.isDirectory()) return null; |
23 | 606 |
607 Set<File> workDirs = new HashSet<File>(); | |
608 File[] files = workFoldersParent.listFiles(new FileFilter() { | |
609 public boolean accept(final File file) { | |
610 return file.isDirectory() && file.getName().startsWith(Settings.DEFAULT_WORK_DIR_PREFIX); | |
611 } | |
612 }); | |
613 if (files != null) { | |
614 for (File f: files) { | |
46 | 615 workDirs.add(PathUtil.getCanonicalFile(f)); |
23 | 616 } |
617 } | |
103 | 618 return workDirs; |
23 | 619 } |
44 | 620 |
621 public String label(@NotNull String label, @NotNull String version, @NotNull VcsRoot root, @NotNull CheckoutRules checkoutRules) throws VcsException { | |
622 syncClonedRepository(root); | |
623 | |
624 Settings settings = createSettings(root); | |
625 | |
626 // I do not know why but hg tag does not work correctly if | |
627 // update command was not invoked for the current repo | |
628 // in such case if there were no tags before Mercurial attempts to | |
629 // create new head when tag is pushed to the parent repository | |
630 UpdateCommand uc = new UpdateCommand(settings); | |
631 uc.execute(); | |
632 | |
633 String fixedTagname = fixTagName(label); | |
634 TagCommand tc = new TagCommand(settings); | |
635 tc.setRevId(new ChangeSet(version).getId()); | |
636 tc.setTag(fixedTagname); | |
637 tc.execute(); | |
638 | |
639 PushCommand pc = new PushCommand(settings); | |
101 | 640 // pc.setForce(true); |
44 | 641 pc.execute(); |
642 return fixedTagname; | |
643 } | |
644 | |
645 private String fixTagName(final String label) { | |
646 // according to Mercurial documentation http://hgbook.red-bean.com/hgbookch8.html#x12-1570008 | |
647 // tag name must not contain: | |
118
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
648 // Colon (ASCII 58, �:�) |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
649 // Carriage return (ASCII 13, �\r�) |
80eb7fdc4de0
Add logging for deleting tmp directories
nd@localhost.localdomain
parents:
106
diff
changeset
|
650 // Newline (ASCII 10, �\n�) |
44 | 651 // all these characters will be replaced with _ (underscore) |
652 return label.replace(':', '_').replace('\r', '_').replace('\n', '_'); | |
653 } | |
654 | |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
655 private Settings createSettings(final VcsRoot root) throws VcsException { |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
656 Settings settings = new Settings(myDefaultWorkFolderParent, root); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
657 String customClonePath = root.getProperty(Constants.SERVER_CLONE_PATH_PROP); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
658 if (!StringUtil.isEmptyOrSpaces(customClonePath) && !myDefaultWorkFolderParent.equals(new File(customClonePath).getAbsoluteFile())) { |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
659 File parentDir = new File(customClonePath); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
660 createClonedRepositoryParentDir(parentDir); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
661 |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
662 // take last part of repository path |
67
e6971dc6b17c
always use url with credentials if username/password are specified
Pavel.Sher
parents:
62
diff
changeset
|
663 String repPath = settings.getRepositoryUrl(); |
62
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
664 String[] splitted = repPath.split("[/\\\\]"); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
665 if (splitted.length > 0) { |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
666 repPath = splitted[splitted.length-1]; |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
667 } |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
668 |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
669 File customWorkingDir = new File(parentDir, repPath); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
670 settings.setWorkingDir(customWorkingDir); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
671 } else { |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
672 createClonedRepositoryParentDir(myDefaultWorkFolderParent); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
673 } |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
674 return settings; |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
675 } |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
676 |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
677 private void createClonedRepositoryParentDir(final File parentDir) throws VcsException { |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
678 if (!parentDir.exists() && !parentDir.mkdirs()) { |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
679 throw new VcsException("Failed to create parent directory for cloned repository: " + parentDir.getAbsolutePath()); |
b328c6b6526d
TW-5636: Mercurial plugin can easilly hit Windows MAX_PATH limitations
Pavel.Sher
parents:
59
diff
changeset
|
680 } |
44 | 681 } |
48 | 682 |
683 public boolean isAgentSideCheckoutAvailable() { | |
684 return true; | |
685 } | |
0 | 686 } |