Mercurial > hg > mercurial
changeset 1123:7f82951e9391 development/2023.11.x
merge default to development/2023.11.x branch
author | Nadia Burnasheva <nadezhda.burnasheva@jetbrains.com> |
---|---|
date | Wed, 18 Oct 2023 13:30:24 +0200 |
parents | 53998d708051 (current diff) e6e3f80c9313 (diff) |
children | |
files | |
diffstat | 31 files changed, 305 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/.idea/artifacts/mercurial_vcs_worker.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/artifacts/mercurial_vcs_worker.xml Wed Oct 18 13:30:24 2023 +0200 @@ -12,8 +12,6 @@ <element id="artifact" artifact-name="mercurial-common.jar" /> <element id="artifact" artifact-name="mercurial-server.jar" /> <element id="library" level="project" name="quartz-2.3.2" /> - <element id="library" level="project" name="commons-compress-1.5" /> - <element id="library" level="project" name="commons-codec-1.4" /> </element> <element id="file-copy" path="$PROJECT_DIR$/teamcity-plugin.xml" /> </root>
--- a/.idea/artifacts/plugin.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/artifacts/plugin.xml Wed Oct 18 13:30:24 2023 +0200 @@ -13,8 +13,6 @@ <element id="artifact" artifact-name="mercurial-common.jar" /> <element id="artifact" artifact-name="mercurial-server-tc.jar" /> <element id="library" level="project" name="quartz-2.3.2" /> - <element id="library" level="project" name="commons-compress-1.5" /> - <element id="library" level="project" name="commons-codec-1.4" /> </element> <element id="directory" name="agent"> <element id="archive" name="mercurial.zip"> @@ -22,8 +20,6 @@ <element id="directory" name="lib"> <element id="artifact" artifact-name="mercurial-common.jar" /> <element id="artifact" artifact-name="mercurial-agent.jar" /> - <element id="library" level="project" name="commons-codec-1.4" /> - <element id="library" level="project" name="commons-compress-1.5" /> </element> </element> </element>
--- a/.idea/libraries/IDEA_openapi.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/libraries/IDEA_openapi.xml Wed Oct 18 13:30:24 2023 +0200 @@ -3,6 +3,8 @@ <CLASSES> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/resources_en.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/util.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/idea-obsolete-openapi.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/logging.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/openapi.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/annotations.jar!/" /> </CLASSES>
--- a/.idea/libraries/Log4j.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/libraries/Log4j.xml Wed Oct 18 13:30:24 2023 +0200 @@ -4,6 +4,9 @@ <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-1.2-api-2.17.2.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-api-2.17.2.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-core-2.17.2.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-1.2-api.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-api.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-core.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES />
--- a/.idea/libraries/TeamCityAPI_agent.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/libraries/TeamCityAPI_agent.xml Wed Oct 18 13:30:24 2023 +0200 @@ -3,6 +3,7 @@ <CLASSES> <root url="jar://$TeamCityDistribution$/devPackage/agent-api.jar!/" /> <root url="jar://$TeamCityDistribution$/buildAgent/lib/agent.jar!/" /> + <root url="jar://$TeamCityDistribution$/buildAgent/lib/agent-core.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES>
--- a/.idea/libraries/TeamCityAPI_common.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/libraries/TeamCityAPI_common.xml Wed Oct 18 13:30:24 2023 +0200 @@ -1,10 +1,22 @@ <component name="libraryTable"> <library name="TeamCityAPI-common"> <CLASSES> + <root url="jar://$TeamCityDistribution$/devPackage/common!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/build-version!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/common-runtime!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/messages!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/patches!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/runtime-util!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/xml-rpc-wrapper!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/common-vcs!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/utils!/" /> + <root url="jar://$TeamCityDistribution$/devPackage/common-tools!/" /> <root url="jar://$TeamCityDistribution$/devPackage/common-api.jar!/" /> <root url="jar://$TeamCityDistribution$/devPackage/serviceMessages.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/commons-httpclient.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/commons-httpclient-3.1.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/commons-logging.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/commons-logging-1.2.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES>
--- a/.idea/libraries/TeamCityAPI_server.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/libraries/TeamCityAPI_server.xml Wed Oct 18 13:30:24 2023 +0200 @@ -2,6 +2,24 @@ <library name="TeamCityAPI-server"> <CLASSES> <root url="jar://$TeamCityDistribution$/devPackage/server-api.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server-core.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/buildLog-common.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/common-step-conditions.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/configs-impl.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/ide-notificator.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/idea-settings.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/messages-processing.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/plugin-model-server.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/ro-server-util.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server-common-api-impl.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server-diagnostic.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server-startup.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server-vcs-api.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server-vcs-api-ex.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server-vcs-impl.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/thread-dump-analyzer.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/vcs-api-impl.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/pipelines-server.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server.jar!/" /> </CLASSES> <JAVADOC />
--- a/.idea/libraries/TeamCity_impl.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/libraries/TeamCity_impl.xml Wed Oct 18 13:30:24 2023 +0200 @@ -2,7 +2,11 @@ <library name="TeamCity-impl"> <CLASSES> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/patches-impl.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/com.github.adedayo.intellij.sdk-trove4j.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove4j-142.1.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/net.sf.trove4j-trove4j!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove4j.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove-3.0.3.jar!/" /> </CLASSES> <JAVADOC />
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.idea/libraries/commons_codec_1_16_0.xml Wed Oct 18 13:30:24 2023 +0200 @@ -0,0 +1,10 @@ +<component name="libraryTable"> + <library name="commons-codec-1.16.0"> + <CLASSES> + <root url="jar://$PROJECT_DIR$/lib/commons-codec-1.16.0.jar!/" /> + <root url="jar://$PROJECT_DIR$/lib/commons-codec.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> +</component> \ No newline at end of file
--- a/.idea/libraries/commons_codec_1_4.xml Tue Oct 17 12:52:06 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -<component name="libraryTable"> - <library name="commons-codec-1.4"> - <CLASSES> - <root url="jar://$PROJECT_DIR$/lib/commons-codec-1.4.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - </library> -</component> \ No newline at end of file
--- a/.idea/libraries/commons_compress_1_5.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/libraries/commons_compress_1_5.xml Wed Oct 18 13:30:24 2023 +0200 @@ -2,6 +2,7 @@ <library name="commons-compress-1.5"> <CLASSES> <root url="jar://$PROJECT_DIR$/lib/commons-compress-1.5.jar!/" /> + <root url="jar://$PROJECT_DIR$/lib/commons-compress.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES />
--- a/.idea/misc.xml Tue Oct 17 12:52:06 2023 +0200 +++ b/.idea/misc.xml Wed Oct 18 13:30:24 2023 +0200 @@ -1,8 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="EntryPointsManager"> - <entry_points version="2.0" /> - </component> - <component name="IdProvider" IDEtalkID="C52C76224CD45BEC1DC62428B699D800" /> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" /> +<project version="4"> + <component name="EntryPointsManager"> + <entry_points version="2.0" /> + </component> + <component name="IdProvider" IDEtalkID="C52C76224CD45BEC1DC62428B699D800" /> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" /> </project> \ No newline at end of file
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java Wed Oct 18 13:30:24 2023 +0200 @@ -37,6 +37,8 @@ boolean runWithProfile(@NotNull AgentRunningBuild build); + boolean retryPullForIllegalPathComponent(@NotNull AgentRunningBuild build); + @NotNull File getTempDir(); }
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java Wed Oct 18 13:30:24 2023 +0200 @@ -96,6 +96,11 @@ return Boolean.parseBoolean(build.getSharedConfigParameters().get("teamcity.hg.runCommandsWithProfile")); } + @Override + public boolean retryPullForIllegalPathComponent(@NotNull AgentRunningBuild build) { + return Boolean.parseBoolean(build.getSharedConfigParameters().getOrDefault("teamcity.hg.retryPullForIllegalPathComponent", "true")); + } + @Nullable public Integer parseTimeout(@Nullable String timeoutStr) { if (timeoutStr == null)
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Wed Oct 18 13:30:24 2023 +0200 @@ -23,6 +23,7 @@ import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.PullCommand; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.AbandonedTransactionFound; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.PathIllegalComponentException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnrelatedRepositoryException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.WrongSubrepoUrlException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.ext.BeforeWorkingDirUpdateExtension; @@ -33,6 +34,7 @@ import jetbrains.buildServer.vcs.VcsException; import jetbrains.buildServer.vcs.VcsRoot; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -57,6 +59,7 @@ private int myPullTimeout; private final boolean myUseTraceback; private final boolean myProfile; + private final boolean myRetryPullForIllegalPathComponent; private final List<MercurialExtension> myExtensions = new ArrayList<>(); protected final MercurialProgress myProgress; @@ -76,6 +79,7 @@ myPullTimeout = pluginConfig.getPullTimeout(build); myUseTraceback = pluginConfig.runWithTraceback(build); myProfile = pluginConfig.runWithProfile(build); + myRetryPullForIllegalPathComponent = pluginConfig.retryPullForIllegalPathComponent(build); myProgress = new MercurialBuildLogProgress(build.getBuildLogger().getFlowLogger("-1")); } @@ -126,16 +130,12 @@ if (mirrorRepo.containsRevision(revision)) { myLogger.message("Local mirror is already up-to-date"); } else { - PullCommand pull = mirrorRepo.pull().fromRepository(repositoryUrl) - .withTraceback(myUseTraceback) - .withProfile(myProfile) - .withTimeout(myPullTimeout); try { - pull.call(); + doPull(mirrorRepo, repositoryUrl, myToVersion); } catch (AbandonedTransactionFound e) { myLogger.message("Abandoned transaction found, trying to recover"); mirrorRepo.recover().call(); - pull.call(); + doPull(mirrorRepo, repositoryUrl, myToVersion); } } } @@ -154,17 +154,36 @@ myLogger.message("Repository already contains revision " + myToVersion); } else { try { - repo.pull().fromRepository(repositoryUrl) - .withTraceback(myUseTraceback) - .withProfile(myProfile) - .withTimeout(myPullTimeout) - .call(); + doPull(repo, repositoryUrl, myToVersion); } catch (UnrelatedRepositoryException e) { throw new UnrelatedRepositoryException(myAuthSettings.getRepositoryUrlWithHiddenPassword(repositoryUrl), workingDir); } } } + private void doPull(@NotNull HgRepo repo, @NotNull String repositoryUrl, @NotNull String revision) throws VcsException { + doPull(repo, repositoryUrl, revision, false); + } + + private void doPull(@NotNull HgRepo repo, @NotNull String repositoryUrl, @NotNull String revision, boolean explicitRevision) throws VcsException { + final PullCommand pullCommand = repo.pull().fromRepository(repositoryUrl) + .withTraceback(myUseTraceback) + .withProfile(myProfile) + .withTimeout(myPullTimeout); + if (explicitRevision) { + pullCommand.withNamedRevision(revision); + } + + try { + pullCommand.call(); + } catch (PathIllegalComponentException e) { + if (!myRetryPullForIllegalPathComponent || explicitRevision) { + throw e; + } + myLogger.message("Pull encountered illegal path component " + e.getComponent() + " retrying with explicit revision " + revision); + doPull(repo, repositoryUrl, revision, true); + } + } private void disableSharing(@NotNull File workingDir) { File dotHg = new File(workingDir, ".hg");
--- a/mercurial-common/mercurial-common.iml Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-common/mercurial-common.iml Wed Oct 18 13:30:24 2023 +0200 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <module relativePaths="true" type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false"> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> <output url="file://$MODULE_DIR$/classes" /> <exclude-output /> <content url="file://$MODULE_DIR$"> @@ -11,6 +11,6 @@ <orderEntry type="library" exported="" name="TeamCityAPI-common" level="project" /> <orderEntry type="library" exported="" name="IDEA-openapi" level="project" /> <orderEntry type="library" name="jdom" level="project" /> - <orderEntry type="library" name="commons-codec-1.4" level="project" /> + <orderEntry type="library" name="commons-codec-1.16.0" level="project" /> </component> </module> \ No newline at end of file
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java Wed Oct 18 13:30:24 2023 +0200 @@ -242,6 +242,7 @@ checkMergeWithWorkDirAncestor(stderr); checkNothingToMerge(stderr); checkUnknownException(stderr); + checkPathIllegalComponent(stderr); } private void checkUnrelatedRepository(@NotNull final String stderr) throws UnrelatedRepositoryException { @@ -298,6 +299,16 @@ throw new UnknownMercurialException(stderr); } + private void checkPathIllegalComponent(@NotNull final String stderr) throws PathIllegalComponentException { + final String prefix = "abort: path contains illegal component: "; + int idx = stderr.indexOf(prefix); + if (idx != -1) { + int startIdx = idx + prefix.length(); + final String component = stderr.substring(startIdx); + throw new PathIllegalComponentException(component); + } + } + private static Set<Integer> setOf(Integer... ints) { return new HashSet<>(asList(ints)); }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java Wed Oct 18 13:30:24 2023 +0200 @@ -31,6 +31,8 @@ private int myTimeout; private boolean myTraceback; private boolean myProfile; + private ChangeSet myChangeSet; + private String myNamedRevision; public PullCommand(@NotNull CommandSettings commandSettings, @NotNull String hgPath, @@ -64,6 +66,16 @@ return this; } + public PullCommand withChangeSet(@NotNull ChangeSet changeSet) { + myChangeSet = changeSet; + return this; + } + + public PullCommand withNamedRevision(@NotNull String namedRevision) { + myNamedRevision = namedRevision; + return this; + } + public void call() throws VcsException { removeLocks(); @@ -84,6 +96,12 @@ cli.setHasProgress(true); } + if (myChangeSet != null) { + cli.addParameters("--rev", myChangeSet.getId()); + } else if (myNamedRevision != null) { + cli.addParameters("--rev", myNamedRevision); + } + String pullUrl = myAuthSettings.getRepositoryUrlWithCredentials(myPullUrl); cli.addParameter(pullUrl); runCommand(cli, settings);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/exception/PathIllegalComponentException.java Wed Oct 18 13:30:24 2023 +0200 @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2023 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception; + +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +public class PathIllegalComponentException extends VcsException { + + @NotNull private final String myComponent; + + public PathIllegalComponentException(@NotNull String component) { + super("Path contains illegal component: " + component); + myComponent = component; + } + + @NotNull + public String getComponent() { + return myComponent; + } +}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Wed Oct 18 13:30:24 2023 +0200 @@ -19,6 +19,7 @@ import jetbrains.buildServer.buildTriggers.vcs.AbstractVcsPropertiesProcessor; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.AbandonedTransactionFound; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.PathIllegalComponentException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnrelatedRepositoryException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.WrongSubrepoUrlException; import jetbrains.buildServer.log.Loggers; @@ -539,8 +540,12 @@ } } + private void syncRepository(@NotNull final HgVcsRoot root, @NotNull final ChangeSet cset) throws VcsException { + syncRepository(root, cset, false); + } + /* clone the repo if it doesn't exist, pull the repo if it doesn't contain specified changeSet */ - private void syncRepository(@NotNull final HgVcsRoot root, @NotNull final ChangeSet cset) throws VcsException { + private void syncRepository(@NotNull final HgVcsRoot root, @NotNull final ChangeSet cset, boolean explicitRevision) throws VcsException { File workingDir = getWorkingDir(root); lockWorkDir(workingDir); HgRepo repo = createRepo(root); @@ -552,14 +557,27 @@ repo.setDefaultPath(root.getRepository()); repo.setTeamCityConfig(root.getCustomHgConfigServer()); try { - repo.pull().fromRepository(root.getRepository()) + final PullCommand pullCommand = repo.pull().fromRepository(root.getRepository()) .withTimeout(myConfig.getPullTimeout()) - .withProfile(myConfig.runWithProfile(root)) - .call(); + .withProfile(myConfig.runWithProfile(root)); + if (explicitRevision) { + pullCommand.withChangeSet(cset); + } + pullCommand.call(); } catch (UnrelatedRepositoryException e) { Loggers.VCS.warn("Repository at " + root.getRepository() + " is unrelated, clone it again"); myMirrorManager.forgetDir(workingDir); syncRepository(root, cset); + } catch (PathIllegalComponentException e) { + final StringBuilder logMessage = new StringBuilder("Pulling from repository at ").append(root.getRepository()) + .append(" failed because of illegal path component ").append(e.getComponent()).append("."); + if (myConfig.retryPullForIllegalPathComponent() && !explicitRevision) { + logMessage.append(" Retrying with explicit pull for revision ").append(cset).append("."); + Loggers.VCS.warn(logMessage.toString()); + syncRepository(root, cset, true); + return; + } + Loggers.VCS.warn(logMessage.toString()); } } finally { unlockWorkDir(workingDir); @@ -581,11 +599,12 @@ public <T> T syncRepository(@NotNull HgVcsRoot root, @NotNull SyncSettings<T> settings, @Nullable OperationContext context) throws VcsException { boolean customWorkingDir = root.getCustomWorkingDir() != null; File workingDir = getWorkingDir(root); + boolean pullFromTip = false; int attemptsLeft = 3; VcsException lastError = null; while (attemptsLeft-- > 0) { try { - return syncRepositoryOnce(root, settings, workingDir, context); + return syncRepositoryOnce(root, settings, workingDir, context, pullFromTip); } catch (UnrelatedRepositoryException e) { if (customWorkingDir) throw new VcsException(e.getMessage() + ". VCS root uses a custom clone dir, manual recovery is required.", e); @@ -600,13 +619,26 @@ + workingDir.getAbsolutePath() + ". Clone it again, attempts left " + attemptsLeft); myMirrorManager.forgetDir(workingDir); lastError = e; + } catch (PathIllegalComponentException e) { + final StringBuilder logMessage = new StringBuilder("Pull failed because of illegal path component ").append(e.getComponent()) + .append(" for repository ").append(root.getRepository()).append(" at ").append(workingDir.getAbsolutePath()).append("."); + if (myConfig.retryPullForIllegalPathComponent()) { + logMessage.append(" Retrying with pull from tip revision, attempts left ").append(attemptsLeft); + pullFromTip = true; + } + Loggers.VCS.warn(logMessage.toString()); + lastError = e; } } throw lastError; } - private <T> T syncRepositoryOnce(@NotNull HgVcsRoot root, @NotNull SyncSettings<T> settings, @NotNull File workingDir, @Nullable OperationContext context) throws VcsException { + private <T> T syncRepositoryOnce(@NotNull HgVcsRoot root, + @NotNull SyncSettings<T> settings, + @NotNull File workingDir, + @Nullable OperationContext context, + boolean fromTip) throws VcsException { lockWorkDir(workingDir, settings.getProgressConsumer()); HgRepo repo = context != null ? context.createRepo(root) : createRepo(root); try { @@ -615,10 +647,13 @@ repo.setDefaultPath(root.getRepository()); repo.setTeamCityConfig(root.getCustomHgConfigServer()); resetBookmarks(repo); - repo.pull().fromRepository(root.getRepository()) + final PullCommand pullCommand = repo.pull().fromRepository(root.getRepository()) .withTimeout(myConfig.getPullTimeout()) - .withProfile(myConfig.runWithProfile(root)) - .call(); + .withProfile(myConfig.runWithProfile(root)); + if (fromTip) { + pullCommand.withNamedRevision("tip"); + } + pullCommand.call(); return settings.getCmd().call(); } finally { unlockWorkDir(workingDir);
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java Wed Oct 18 13:30:24 2023 +0200 @@ -37,6 +37,7 @@ public class ServerHgRepo extends HgRepo { public final static HgVersion REVSET_HG_VERSION = new HgVersion(1, 7, 0); + public final static HgVersion MERGE_WITHOUT_CHANGED_FILES_VERSION = new HgVersion(5, 2, 0); private final CommandSettingsFactory myCommandSettingsFactory; private final ServerPluginConfig myConfig; protected final MercurialClasspathTemplate myLogTemplate = new MercurialClasspathTemplate("/buildServerResources/log.template", "hg.log.template"); @@ -99,6 +100,12 @@ return hgVersion.isEqualsOrGreaterThan(REVSET_HG_VERSION); } + // mercurial > 5.1 no longer reports changed files for the merge commits, see https://youtrack.jetbrains.com/issue/TW-79815 + public boolean supportsChangedFilesForMerges() throws VcsException { + HgVersion hgVersion = getHgVersion(); + return hgVersion.isLessThan(MERGE_WITHOUT_CHANGED_FILES_VERSION); + } + private HgVersion getHgVersion() throws VcsException { if (myContext != null) return myContext.getHgVersion(this);
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java Wed Oct 18 13:30:24 2023 +0200 @@ -61,4 +61,6 @@ boolean runWithProfile(@NotNull HgVcsRoot root); boolean computeFromRevisions(); + + boolean retryPullForIllegalPathComponent(); }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java Wed Oct 18 13:30:24 2023 +0200 @@ -133,4 +133,8 @@ public boolean computeFromRevisions() { return TeamCityProperties.getBooleanOrTrue("teamcity.hg.computeFromRevisions"); } + + public boolean retryPullForIllegalPathComponent() { + return TeamCityProperties.getBooleanOrTrue("teamcity.hg.retryPullForIllegalPathComponent"); + } }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesWithRevsets.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesWithRevsets.java Wed Oct 18 13:30:24 2023 +0200 @@ -52,9 +52,22 @@ revsets.append(" + ").append(from); } } - return myRepo.log(myRoot) + List<ChangeSet> result = myRepo.log(myRoot) .showCommitsFromAllBranches() .withRevsets(revsets.toString()) .call(); + + if (!myRepo.supportsChangedFilesForMerges()) { + for (ChangeSet cs: result) { + if (cs.getParents().size() > 1) { + // new version of Mercurial does not include merge commit changed files into the log + // let's fetch the files with a separate command (https://youtrack.jetbrains.com/issue/TW-79815) + final List<FileStatus> files = myRepo.status().fromRevision(cs.getParents().get(0).getId()).toRevision(cs.getId()).call(); + cs.setModifiedFiles(files); + } + } + } + + return result; } }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java Wed Oct 18 13:30:24 2023 +0200 @@ -16,6 +16,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; +import com.intellij.openapi.util.SystemInfo; import jetbrains.buildServer.agent.AgentRunningBuild; import jetbrains.buildServer.agent.BuildAgentConfiguration; import jetbrains.buildServer.agent.BuildProgressLogger; @@ -32,6 +33,7 @@ import org.jetbrains.annotations.NotNull; import org.jmock.Expectations; import org.jmock.Mockery; +import org.testng.SkipException; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -114,6 +116,11 @@ public void turn_off_sharing() throws Exception { + // TODO: TW-84326: share extension doesn't work as expected on ARM agents + if (SystemInfo.isARM64) { + throw new SkipException("Ignore test on ARM64 machine"); + } + File myR1Dir = copy(new File("mercurial-tests/testData/subrepos/r1")); copy(new File("mercurial-tests/testData/subrepos/r2")); copy(new File("mercurial-tests/testData/subrepos/r3"));
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java Wed Oct 18 13:30:24 2023 +0200 @@ -68,7 +68,6 @@ return vcs; } - public MercurialSupportBuilder withConfig(@NotNull ServerPluginConfig config) { myConfig = config; return this;
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java Wed Oct 18 13:30:24 2023 +0200 @@ -17,6 +17,7 @@ import com.intellij.openapi.util.SystemInfo; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.PathIllegalComponentException; import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.util.TestFor; import jetbrains.buildServer.vcs.*; @@ -809,6 +810,26 @@ CheckoutRules.DEFAULT); } + @TestFor(issues = "TW-83599") + public void should_retry_pull_on_illegal_path_component() throws Exception { + final VcsRootImpl vcsRoot = createVcsRoot(simpleRepo()); + // we can't realiably force illegal path component errors with real hg repos + final RepoFactory failOnceRepoFactory = failOnceRepoFactory(new PathIllegalComponentException("some-component")); + myVcs = mercurialSupport().withConfig(myPluginConfig).withRepoFactory(failOnceRepoFactory).build(); + + myVcs.syncRepository(vcsRoot); + } + + @TestFor(issues = "TW-83599") + public void get_content_should_retry_pull_on_illegal_path_component() throws IOException, VcsException { + VcsRootImpl vcsRoot = createVcsRoot(simpleRepo()); + // we can't realiably force illegal path component errors with real hg repos + final RepoFactory failOnceRepoFactory = failOnceRepoFactory(new PathIllegalComponentException("some-component")); + myVcs = mercurialSupport().withConfig(myPluginConfig).withRepoFactory(failOnceRepoFactory).build(); + + byte[] content = myVcs.getContent("dir1/subdir/file2.txt", vcsRoot, "4:b06a290a363b"); + assertEquals(new String(content), "bbb"); + } private void assertFiles(final List<String> expectedFiles, final ModificationData modificationData) { Set<String> actualFiles = new HashSet<>(); @@ -838,5 +859,36 @@ public void test_collect_changes_using_checkout_rules() { assertTrue(myVcs.getCollectChangesPolicy() instanceof CollectChangesByCheckoutRules); } + + @NotNull + private RepoFactory failOnceRepoFactory(@NotNull VcsException failure) throws IOException { + final CommandSettingsForRootImpl commandSettingsFactory = new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver(), new CommandlineViaFileWrapperWeaver()); + + return new RepoFactory(myPluginConfig, commandSettingsFactory, myHgPathProvider) { + private boolean myDidFail = false; + + @NotNull + @Override + public ServerHgRepo createRepo(@NotNull HgVcsRoot root, @NotNull File workingDir) throws VcsException { + if (myDidFail) { + return super.createRepo(root, workingDir); + } else { + myDidFail = true; + final CommandSettingsFactory rootSettingsFactory = commandSettingsFactory.forRoot(root); + return new ServerHgRepo(rootSettingsFactory, myConfig, workingDir, myHgPathProvider.getHgPath(root), root.getAuthSettings()) { + @Override + public PullCommand pull() { + return new PullCommand(rootSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings) { + @Override + public void call() throws VcsException { + throw failure; + } + }; + } + }; + } + } + }; + } }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java Wed Oct 18 13:30:24 2023 +0200 @@ -115,6 +115,10 @@ public boolean computeFromRevisions() { return true; } + + public boolean retryPullForIllegalPathComponent() { + return true; + } }; }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResultTest.java Tue Oct 17 12:52:06 2023 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResultTest.java Wed Oct 18 13:30:24 2023 +0200 @@ -21,6 +21,7 @@ import jetbrains.buildServer.ExecResult; import jetbrains.buildServer.StreamGobbler; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.AbandonedTransactionFound; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.PathIllegalComponentException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnknownRevisionException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnrelatedRepositoryException; import jetbrains.buildServer.util.TestFor; @@ -136,6 +137,16 @@ } } + public void should_detect_illegal_path_component() throws VcsException { + final CommandResult commandResult = commandResultFor(execResult().withStderr("abort: path contains illegal component: /_mercurial_classpath_template.java.i")); + try { + commandResult.checkCommandFailed(); + fail("expected PathIllegalComponentException to be thrown"); + } catch (PathIllegalComponentException e) { + assertEquals("/_mercurial_classpath_template.java.i", e.getComponent()); + } + } + public void exception_should_not_contain_command_stdout_or_stderr() { final String stdout = "300Mb of output"; final String stderr = "300Mb from stderr";