# HG changeset patch # User Andreas Eisele # Date 1696932700 -7200 # Node ID 54472aa4b7b20f9f578b07690ebeb60de8f02948 # Parent c1a251997254188fca1e9116c8a747168b47994e TW-83599: recognize "path contains illegal component" error and retry pull command with explicit revision, agent side logic diff -r c1a251997254 -r 54472aa4b7b2 mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java --- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java Mon Oct 09 18:18:26 2023 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfig.java Tue Oct 10 12:11:40 2023 +0200 @@ -37,6 +37,8 @@ boolean runWithProfile(@NotNull AgentRunningBuild build); + boolean retryPullForIllegalPathComponent(@NotNull AgentRunningBuild build); + @NotNull File getTempDir(); } diff -r c1a251997254 -r 54472aa4b7b2 mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java --- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java Mon Oct 09 18:18:26 2023 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java Tue Oct 10 12:11:40 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) diff -r c1a251997254 -r 54472aa4b7b2 mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java --- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Mon Oct 09 18:18:26 2023 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java Tue Oct 10 12:11:40 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 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,37 @@ 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, @Nullable String revision) throws VcsException { + doPull(repo, repositoryUrl, revision, false); + } + + private void doPull(@NotNull HgRepo repo, @NotNull String repositoryUrl, @Nullable String revision, boolean explicitRevision) throws VcsException { + final String effectiveRevision = revision != null ? revision : "tip"; + final PullCommand pullCommand = repo.pull().fromRepository(repositoryUrl) + .withTraceback(myUseTraceback) + .withProfile(myProfile) + .withTimeout(myPullTimeout); + if (explicitRevision) { + pullCommand.withNamedRevision(effectiveRevision); + } + + try { + pullCommand.call(); + } catch (PathIllegalComponentException e) { + if (!myRetryPullForIllegalPathComponent || explicitRevision) { + throw e; + } + myLogger.message("Pull encountered illegal path component " + e.getComponent() + " retrying with explicit revision " + effectiveRevision); + doPull(repo, repositoryUrl, revision, true); + } + } private void disableSharing(@NotNull File workingDir) { File dotHg = new File(workingDir, ".hg");