Mercurial > hg > mercurial
changeset 801:ea4a75bf2324
Merge branch Gaya-8.1.x
author | Dmitry Neverov <dmitry.neverov@jetbrains.com> |
---|---|
date | Mon, 26 May 2014 16:30:19 +0200 |
parents | b130c7d27c02 (diff) d94cdfbd9e1c (current diff) |
children | 005ea6b2dc0f |
files | |
diffstat | 47 files changed, 880 insertions(+), 286 deletions(-) [+] |
line wrap: on
line diff
--- a/.idea/libraries/TeamCity_impl.xml Mon May 26 16:26:58 2014 +0200 +++ b/.idea/libraries/TeamCity_impl.xml Mon May 26 16:30:19 2014 +0200 @@ -3,6 +3,7 @@ <CLASSES> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/patches-impl.jar!/" /> <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove4j.jar!/" /> + <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove-3.0.3.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES />
--- a/mercurial-agent/src/META-INF/build-agent-plugin-mercurial.xml Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-agent/src/META-INF/build-agent-plugin-mercurial.xml Mon May 26 16:30:19 2014 +0200 @@ -26,4 +26,7 @@ <bean id="mirrorCleaner" class="jetbrains.buildServer.buildTriggers.vcs.mercurial.AgentMirrorCleaner" /> <bean id="commandSettingsFactory" class="jetbrains.buildServer.buildTriggers.vcs.mercurial.AgentCommandSettingsFactory" /> <bean id="agentRepoFactory" class="jetbrains.buildServer.buildTriggers.vcs.mercurial.AgentRepoFactory"/> + + <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl"/> + <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver"/> </beans>
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentCommandSettingsFactory.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentCommandSettingsFactory.java Mon May 26 16:30:19 2014 +0200 @@ -18,9 +18,11 @@ import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettings; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsFactory; +import org.jetbrains.annotations.NotNull; public class AgentCommandSettingsFactory implements CommandSettingsFactory { + @NotNull public CommandSettings create() { return new CommandSettings().setLogLevel("info"); }
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentRepoFactory.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentRepoFactory.java Mon May 26 16:30:19 2014 +0200 @@ -16,8 +16,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsFactory; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRoot; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; @@ -26,23 +25,16 @@ public class AgentRepoFactory implements HgRepoFactory { - private final CommandSettingsFactory myCommandSettingsFactory; + private final CommandSettingsForRoot myCommandSettingsFactory; private final HgPathProvider myHgPathProvider; - public AgentRepoFactory(@NotNull CommandSettingsFactory commandSettingsFactory, + public AgentRepoFactory(@NotNull CommandSettingsForRoot commandSettingsFactory, @NotNull HgPathProvider hgPathProvider) { myCommandSettingsFactory = commandSettingsFactory; myHgPathProvider = hgPathProvider; } public HgRepo createRepo(@NotNull HgVcsRoot root, @NotNull File workingDir) throws VcsException { - return new HgRepo(myCommandSettingsFactory, workingDir, myHgPathProvider.getHgPath(root), root.getAuthSettings()); + return new HgRepo(myCommandSettingsFactory.forRoot(root), workingDir, myHgPathProvider.getHgPath(root), root.getAuthSettings()); } - - public HgRepo create(@NotNull File workingDir, - @NotNull String hgPath, - @NotNull AuthSettings authSettings) { - return new HgRepo(myCommandSettingsFactory, workingDir, hgPath, authSettings); - } - }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java Mon May 26 16:30:19 2014 +0200 @@ -32,6 +32,7 @@ String USE_TAGS_AS_BRANCHES = "useTagsAsBranches"; String INCLUDE_SUBREPOS_IN_PATCH = "includeSubreposInPatch"; String USE_ARCHIVE_FOR_PATCH = "useArchiveForPatch"; + String HG_EXTENSIONS = "hg.extensions"; String GLOBAL_DETECT_SUBREPO_CHANGES = "teamcity.hg.detectSubrepoChanges"; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialClasspathTemplate.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2014 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; + +import jetbrains.buildServer.util.FileUtil; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; + +import static com.intellij.openapi.util.io.FileUtil.createTempFile; +import static com.intellij.openapi.util.io.FileUtil.delete; + +/** +* Created 25.02.14 11:29 +* +* @author Eugene Petrenko (eugene.petrenko@jetbrains.com) +*/ +public class MercurialClasspathTemplate implements MercurialTemplate { + private final String myResourcePath; + private final String myTmpFileSuffix; + + public MercurialClasspathTemplate(@NotNull final String resourcePath, + @NotNull final String tmpFileSuffix) { + myResourcePath = resourcePath; + myTmpFileSuffix = tmpFileSuffix; + } + + @NotNull + public <T> T withTemplate(@NotNull final WithTemplate<T> action) throws VcsException { + //TODO: we may pack plugin and use jetbrains.buildServer.web.openapi.PluginDescriptor.getPluginRoot() + //TODO: to get path to existing file + final File template = copyTemplate(); + try { + return action.action(template); + } finally { + delete(template); + } + } + + private File copyTemplate() throws VcsException { + try { + final File template = createTempFile("teamcity", myTmpFileSuffix); + FileUtil.copyResource(getClass(), myResourcePath, template); + return template; + } catch (IOException e) { + throw new VcsException("Cannot create mercurial log template", e); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialTemplate.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2014 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; + +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +/** + * Created 25.02.14 11:51 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public interface MercurialTemplate { + @NotNull + <T> T withTemplate(@NotNull WithTemplate<T> action) throws VcsException; + + interface WithTemplate<T> { + @NotNull + T action(@NotNull final File template) throws VcsException; + } +}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ArchiveCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ArchiveCommand.java Mon May 26 16:30:19 2014 +0200 @@ -92,16 +92,18 @@ cli.addParameter("archive"); setType(cli); setRevision(cli); + addIncludeRules(cli); setDestination(cli); - addIncludeRules(cli); return cli; } private void addIncludeRules(@NotNull MercurialCommandLine cli) { if (myIncludeRules.isEmpty()) return; - cli.addParameter("-I"); - cli.addParameters(myIncludeRules); + for (String include : myIncludeRules) { + cli.addParameter("-I"); + cli.addParameter(include); + } } private void setDestination(GeneralCommandLine cli) {
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommand.java Mon May 26 16:30:19 2014 +0200 @@ -32,9 +32,9 @@ private final String myHgPath; private final File myWorkDirectory; - public BaseCommand(@NotNull CommandSettings commandSettings, + public BaseCommand(@NotNull final CommandSettings commandSettings, @NotNull final String hgPath, - @NotNull File workingDir) { + @NotNull final File workingDir) { myCommandSettings = commandSettings; myHgPath = hgPath; myWorkDirectory = workingDir; @@ -52,17 +52,29 @@ } protected MercurialCommandLine createCL() { - MercurialCommandLine cl = new MercurialCommandLine(getPrivateData()); + final MercurialCommandLine cl = new MercurialCommandLine(getPrivateData()); cl.setExePath(myHgPath); cl.setEnvParams(myCommandSettings.getHgEnv()); cl.setPassParentEnvs(true); + + //include global arguments if any + cl.addParameters(myCommandSettings.getGlobalArguments()); + return cl; } - protected CommandResult runCommand(@NotNull MercurialCommandLine cli) throws VcsException { - return CommandUtil.runCommand(cli, myCommandSettings); + @NotNull + protected final CommandResult runCommand(@NotNull MercurialCommandLine cli) throws VcsException { + return runCommand(cli, myCommandSettings); } + @NotNull + protected final CommandResult runCommand(@NotNull final MercurialCommandLine cli, + @NotNull final CommandSettings commandSettings) throws VcsException { + return CommandUtil.runCommand(cli, commandSettings.setPrivateData(getPrivateData())); + } + + @NotNull protected Set<String> getPrivateData() { return emptySet(); }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CloneCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CloneCommand.java Mon May 26 16:30:19 2014 +0200 @@ -29,6 +29,7 @@ private boolean myUsePullProtocol = true; private boolean myUseUncompressedTransfer = false; private boolean myTraceback; + private ProgressParser.ProgressConsumer myProgressConsumer; public CloneCommand(@NotNull CommandSettings commandSettings, @NotNull String hgPath, @@ -76,6 +77,11 @@ return this; } + public CloneCommand withProgressConsumer(ProgressParser.ProgressConsumer progressConsumer) { + myProgressConsumer = progressConsumer; + return this; + } + public void call() throws VcsException { myWorkingDir.mkdirs(); MercurialCommandLine cli = createCommandLine(); @@ -96,10 +102,20 @@ if (myUseUncompressedTransfer) { cli.addParameter("--uncompressed"); } + + CommandSettings settings = myCommandSettings.setTimeout(24 * 3600); // some repositories are quite large, we set timeout to 24 hours + if (myProgressConsumer != null) { + cli.addParameters("--config", "extensions.progress="); + cli.addParameters("--config", "progress.format=topic number"); + cli.addParameters("--config", "progress.delay=0"); + cli.addParameters("--config", "progress.assume-tty=True"); + settings.setProgressConsumer(myProgressConsumer); + } + String repositoryUrl = myAuthSettings.getRepositoryUrlWithCredentials(myRepository); cli.addParameter(repositoryUrl); cli.addParameter(myWorkingDir.getName()); - runCommand(cli, myCommandSettings.setTimeout(24 * 3600)); // some repositories are quite large, we set timeout to 24 hours + runCommand(cli, settings); } }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandSettings.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandSettings.java Mon May 26 16:30:19 2014 +0200 @@ -18,10 +18,7 @@ import org.jetbrains.annotations.NotNull; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * @author dmitry.neverov @@ -29,41 +26,38 @@ public class CommandSettings { private int myTimeout = 3600; - private Set<String> myPrivateData = new HashSet<String>(); + private final Set<String> myPrivateData = new HashSet<String>(); private boolean myCheckForFailure = true; private boolean myFailWhenStderrNotEmpty = false; private String myLogLevel = "debug"; private Map<String, String> myHgEnv = new HashMap<String, String>(); private int myLogOutputLimit = -1; private int myExceptionOutputLimit = 5000; - - public CommandSettings() { - - } - - public CommandSettings(int timeout, - @NotNull Set<String> privateData, - boolean checkForFailure, - boolean failWhenStderrNotEmpty, - @NotNull String logLevel) { - myTimeout = timeout; - myPrivateData = privateData; - myCheckForFailure = checkForFailure; - myFailWhenStderrNotEmpty = failWhenStderrNotEmpty; - myLogLevel = logLevel; - } + private List<String> myGlobalArguments = new ArrayList<String>(0); + private ProgressParser.ProgressConsumer myProgressConsumer; public CommandSettings setTimeout(int timeout) { myTimeout = timeout; return this; } + @NotNull + public List<String> getGlobalArguments() { + return myGlobalArguments; + } + + @NotNull + public CommandSettings withGlobalArguments(@NotNull String... argz) { + myGlobalArguments.addAll(Arrays.asList(argz)); + return this; + } + public int getTimeout() { return myTimeout; } public CommandSettings setPrivateData(@NotNull Set<String> privateData) { - myPrivateData = privateData; + myPrivateData.addAll(privateData); return this; } @@ -124,4 +118,12 @@ public void setExceptionOutputLimit(int limit) { myExceptionOutputLimit = limit; } + + public ProgressParser.ProgressConsumer getProgressConsumer() { + return myProgressConsumer; + } + + public void setProgressConsumer(ProgressParser.ProgressConsumer progressConsumer) { + myProgressConsumer = progressConsumer; + } }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandSettingsFactory.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandSettingsFactory.java Mon May 26 16:30:19 2014 +0200 @@ -16,8 +16,11 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; +import org.jetbrains.annotations.NotNull; + public interface CommandSettingsFactory { + @NotNull CommandSettings create(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandSettingsForRoot.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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; + +import org.jetbrains.annotations.NotNull; + +/** + * Created 25.02.14 12:58 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public interface CommandSettingsForRoot { + @NotNull CommandSettingsFactory forRoot(@NotNull HgVcsRoot root); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandSettingsForRootImpl.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2014 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; + +import org.jetbrains.annotations.NotNull; + +/** + * Created 25.02.14 13:01 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public class CommandSettingsForRootImpl implements CommandSettingsForRoot { + private final CommandSettingsFactory myFactory; + private final CommandSettingsWeaver[] myWeavers; + + public CommandSettingsForRootImpl(@NotNull CommandSettingsFactory factory, + @NotNull final CommandSettingsWeaver... weavers) { + myFactory = factory; + myWeavers = weavers; + } + + @NotNull + public CommandSettingsFactory forRoot(@NotNull final HgVcsRoot root) { + return new CommandSettingsFactory() { + @NotNull + public CommandSettings create() { + CommandSettings settings = myFactory.create(); + for (CommandSettingsWeaver weaver : myWeavers) { + settings = weaver.update(root, settings); + } + return settings; + } + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandSettingsWeaver.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2014 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; + +import org.jetbrains.annotations.NotNull; + +/** + * Created 25.02.14 13:02 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public interface CommandSettingsWeaver { + @NotNull + CommandSettings update(@NotNull HgVcsRoot root, @NotNull CommandSettings settings); +}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java Mon May 26 16:30:19 2014 +0200 @@ -16,13 +16,16 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; import jetbrains.buildServer.ExecResult; +import jetbrains.buildServer.LineAwareByteArrayOutputStream; import jetbrains.buildServer.SimpleCommandLineProcessRunner; import jetbrains.buildServer.log.Loggers; import jetbrains.buildServer.util.StringUtil; import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.nio.charset.Charset; import java.util.Set; public class CommandUtil { @@ -43,17 +46,26 @@ @NotNull final Set<String> privateData, @NotNull CommandSettings settings) { final long start = System.currentTimeMillis(); - ExecResult res = SimpleCommandLineProcessRunner.runCommand(cli, null, new SimpleCommandLineProcessRunner.ProcessRunCallbackAdapter() { + ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + ProgressParser.ProgressConsumer progressConsumer = settings.getProgressConsumer(); + ByteArrayOutputStream stderrBuffer; + if (progressConsumer != null) { + stderrBuffer = new LineAwareByteArrayOutputStream(Charset.forName("UTF-8"), new ProgressParser(progressConsumer)); + ((LineAwareByteArrayOutputStream) stderrBuffer).setCREndsLine(true); + } else { + stderrBuffer = new ByteArrayOutputStream(); + } + ExecResult res = SimpleCommandLineProcessRunner.runCommandSecure(cli, command, null, new SimpleCommandLineProcessRunner.ProcessRunCallbackAdapter() { @Override public Integer getOutputIdleSecondsTimeout() { return executionTimeout; } @Override - public void onProcessFinished(Process ps) { + public void onProcessFinished(@NotNull Process ps) { long duration = System.currentTimeMillis() - start; Loggers.VCS.debug("Command " + command + " took " + duration + "ms"); } - }); + }, stdoutBuffer, stderrBuffer); return new CommandResult(Loggers.VCS, command, res, privateData, settings); }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommitsAndMountPointsCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommitsAndMountPointsCommand.java Mon May 26 16:30:19 2014 +0200 @@ -16,9 +16,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgFileUtil; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgRepo; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgVersion; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.*; import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ExtensionsWeaver.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2014 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; + +import jetbrains.buildServer.buildTriggers.vcs.mercurial.Constants; +import jetbrains.buildServer.util.StringUtil; +import org.jetbrains.annotations.NotNull; + +/** + * Created 25.02.14 13:03 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public class ExtensionsWeaver implements CommandSettingsWeaver { + @NotNull + public CommandSettings update(@NotNull HgVcsRoot root, @NotNull CommandSettings settings) { + String extensions = root.getProperty(Constants.HG_EXTENSIONS); + if (StringUtil.isEmpty(extensions)) return settings; + + for (String _line : extensions.split("[\\r\\n]+")) { + String line = _line.trim(); + if (line.isEmpty()) continue; + + if (!line.contains("=")) line += "="; + + settings = settings.withGlobalArguments("--config", "extensions." + line); + } + + return settings; + } +}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LoadDagCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LoadDagCommand.java Mon May 26 16:30:19 2014 +0200 @@ -17,6 +17,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; import com.intellij.openapi.util.Pair; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialTemplate; import jetbrains.buildServer.util.StringUtil; import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; @@ -27,14 +28,14 @@ public class LoadDagCommand extends VcsRootCommand { - private final File myDagLogTemplate; + private final MercurialTemplate myDagLogTemplate; private int myMaxDagNodesCount; public LoadDagCommand(@NotNull CommandSettings commandSettings, @NotNull String hgPath, @NotNull File workingDir, @NotNull AuthSettings authSettings, - @NotNull File dagLogTemplate) { + @NotNull MercurialTemplate dagLogTemplate) { super(commandSettings, hgPath, workingDir, authSettings); myDagLogTemplate = dagLogTemplate; } @@ -45,31 +46,42 @@ @NotNull public List<Pair<String, String>> call() throws VcsException { - List<Pair<String, String>> edges = new ArrayList<Pair<String, String>>(); - MercurialCommandLine cli = createCommandLine(); - cli.addParameter("log"); - cli.addParameter("--style=" + myDagLogTemplate.getAbsolutePath()); - if (myMaxDagNodesCount > 0) - cli.addParameters("--limit", String.valueOf(myMaxDagNodesCount)); - CommandResult res = runCommand(cli); - String output = res.getStdout(); - String fromNode = null; - for (String line : StringUtil.splitByLines(output)) { - String[] revs = line.split(" "); - if (revs.length == 0) - continue; - if (fromNode != null) { - edges.add(Pair.create(fromNode, revs[0])); - fromNode = null; + return myDagLogTemplate.withTemplate(new MercurialTemplate.WithTemplate<List<Pair<String, String>>>() { + @NotNull + public List<Pair<String, String>> action(@NotNull File template) throws VcsException { + final List<Pair<String, String>> edges = new ArrayList<Pair<String, String>>(); + final MercurialCommandLine cli = createCommandLine(); + cli.addParameter("log"); + cli.addParameter("--style=" + template.getAbsolutePath()); + if (myMaxDagNodesCount > 0) { + cli.addParameters("--limit", String.valueOf(myMaxDagNodesCount)); + } + + final CommandResult res = runCommand(cli); + + + final String output = res.getStdout(); + String fromNode = null; + for (String line : StringUtil.splitByLines(output)) { + final String[] revs = line.split(" "); + if (revs.length == 0) continue; + + if (fromNode != null) { + edges.add(Pair.create(fromNode, revs[0])); + fromNode = null; + } + + if (revs.length == 1) { + fromNode = revs[0]; + } else { + edges.add(Pair.create(revs[0], revs[1])); + if (revs.length == 3) { + edges.add(Pair.create(revs[0], revs[2])); + } + } + } + return edges; } - if (revs.length == 1) { - fromNode = revs[0]; - } else { - edges.add(Pair.create(revs[0], revs[1])); - if (revs.length == 3) - edges.add(Pair.create(revs[0], revs[2])); - } - } - return edges; + }); } }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java Mon May 26 16:30:19 2014 +0200 @@ -16,6 +16,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; import com.intellij.openapi.diagnostic.Logger; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialTemplate; import jetbrains.buildServer.util.StringUtil; import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; @@ -44,7 +45,7 @@ private String myBranchName; private boolean myCalculateParents = true; private String myRevsets; - private File myTemplate; + private MercurialTemplate myTemplate; private List<String> myFiles = new ArrayList<String>(); public LogCommand(@NotNull CommandSettings commandSettings, @@ -54,7 +55,7 @@ super(commandSettings, hgPath, workingDir, authSettings); } - public LogCommand withTemplate(@NotNull File template) { + public LogCommand withTemplate(@NotNull MercurialTemplate template) { myTemplate = template; return this; } @@ -104,49 +105,57 @@ return this; } + @NotNull public List<ChangeSet> call() throws VcsException { - MercurialCommandLine cli = createCommandLine(); - cli.setCharset(Charset.forName("UTF-8")); - cli.addParameters("--encoding", "UTF-8"); - cli.addParameter("log"); - cli.addParameter("-v"); - if (myTemplate != null) - cli.addParameter("--style=" + myTemplate.getAbsolutePath()); - if (myBranchName != null) { - cli.addParameter("-b"); - cli.addParameter(myBranchName); - } - cli.addParameter("-r"); - if (myRevsets != null) { - cli.addParameter(myRevsets); - } else { - String from = myFromId != null ? myFromId : "0"; - String to = myToId != null ? myToId : "tip"; - cli.addParameter(from + ":" + to); - } - if (myLimit != null) { - cli.addParameter("--limit"); - cli.addParameter(myLimit.toString()); - } + return myTemplate.withTemplate(new MercurialTemplate.WithTemplate<List<ChangeSet>>() { + @NotNull + public List<ChangeSet> action(@NotNull File template) throws VcsException { + final MercurialCommandLine cli = createCommandLine(); + cli.setCharset(Charset.forName("UTF-8")); + cli.addParameters("--encoding", "UTF-8"); + cli.addParameter("log"); + cli.addParameter("-v"); + if (myTemplate != null) { + cli.addParameter("--style=" + template.getAbsolutePath()); + } - cli.addParameters(myFiles); + if (myBranchName != null) { + cli.addParameter("-b"); + cli.addParameter(myBranchName); + } + cli.addParameter("-r"); + if (myRevsets != null) { + cli.addParameter(myRevsets); + } else { + String from = myFromId != null ? myFromId : "0"; + String to = myToId != null ? myToId : "tip"; + cli.addParameter(from + ":" + to); + } + if (myLimit != null) { + cli.addParameter("--limit"); + cli.addParameter(myLimit.toString()); + } + + cli.addParameters(myFiles); - CommandResult res = runCommand(cli); - String output = res.getStdout(); - try { - List<ChangeSet> changes = parseChangeSetsXml(output); - if (myCalculateParents) - assignTrivialParents(changes); - return changes; - } catch (Exception e) { - int limit = myCommandSettings.getLogOutputLimit(); - if (limit == -1) { - LOG.error("Error while parsing log output:\n" + output, e); - } else { - LOG.error("Error while parsing log output:\n" + StringUtil.truncateStringValueWithDotsAtEnd(output, limit), e); + final CommandResult res = runCommand(cli); + final String output = res.getStdout(); + try { + List<ChangeSet> changes = parseChangeSetsXml(output); + if (myCalculateParents) + assignTrivialParents(changes); + return changes; + } catch (Exception e) { + int limit = myCommandSettings.getLogOutputLimit(); + if (limit == -1) { + LOG.error("Error while parsing log output:\n" + output, e); + } else { + LOG.error("Error while parsing log output:\n" + StringUtil.truncateStringValueWithDotsAtEnd(output, limit), e); + } + throw new VcsException("Error while parsing log output, see teamcity-vcs.log for details", e); + } } - throw new VcsException("Error while parsing log output, see teamcity-vcs.log for details", e); - } + }); } private List<ChangeSet> parseChangeSetsXml(@NotNull final String xml) throws SAXException, ParserConfigurationException, IOException {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ProgressParser.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2014 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; + +import jetbrains.buildServer.LineAwareByteArrayOutputStream; +import org.jetbrains.annotations.NotNull; + +public class ProgressParser implements LineAwareByteArrayOutputStream.LineListener { + + private final ProgressConsumer myConsumer; + + public ProgressParser(@NotNull ProgressConsumer consumer) { + myConsumer = consumer; + } + + public interface ProgressConsumer { + void consume(float progress, @NotNull String stage); + } + + public void newLineDetected(@NotNull String line) { + String trimmed = line.trim(); + if (trimmed.isEmpty()) + return; + + int spaceIdx = trimmed.indexOf(' '); + if (spaceIdx == -1) { + myConsumer.consume(-1, trimmed); + return; + } + + String stage = trimmed.substring(0, spaceIdx); + String progress = trimmed.substring(spaceIdx).trim(); + int ratioIdx = progress.indexOf('/'); + if (ratioIdx == -1 || ratioIdx == trimmed.length() - 1) { + myConsumer.consume(-1, stage); + return; + } + + try { + int nom = Integer.parseInt(progress.substring(0, ratioIdx)); + int denom = Integer.parseInt(progress.substring(ratioIdx+1)); + myConsumer.consume(nom * 1.0f / denom, stage); + } catch (NumberFormatException e) { + myConsumer.consume(-1, stage); + } + } +}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java Mon May 26 16:30:19 2014 +0200 @@ -32,6 +32,7 @@ private String myPullUrl; private int myTimeout; private boolean myTraceback; + private ProgressParser.ProgressConsumer myProgressConsumer; public PullCommand(@NotNull CommandSettings commandSettings, @NotNull String hgPath, @@ -60,15 +61,30 @@ return this; } + public PullCommand withProgressConsumer(ProgressParser.ProgressConsumer progressConsumer) { + myProgressConsumer = progressConsumer; + return this; + } + public void call() throws VcsException { ensureRepositoryIsNotLocked(); MercurialCommandLine cli = createCommandLine(); cli.addParameter("pull"); if (myTraceback) cli.addParameter("--traceback"); - String pullUrl = myAuthSettings != null ? myAuthSettings.getRepositoryUrlWithCredentials(myPullUrl) : myPullUrl; + + CommandSettings settings = myCommandSettings.setTimeout(myTimeout); + if (myProgressConsumer != null) { + cli.addParameters("--config", "extensions.progress="); + cli.addParameters("--config", "progress.format=topic number"); + cli.addParameters("--config", "progress.delay=0"); + cli.addParameters("--config", "progress.assume-tty=True"); + settings.setProgressConsumer(myProgressConsumer); + } + + String pullUrl = myAuthSettings.getRepositoryUrlWithCredentials(myPullUrl); cli.addParameter(pullUrl); - runCommand(cli, myCommandSettings.setTimeout(myTimeout)); + runCommand(cli, settings); } private void ensureRepositoryIsNotLocked() {
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/VcsRootCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/VcsRootCommand.java Mon May 26 16:30:19 2014 +0200 @@ -16,7 +16,6 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; -import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -40,12 +39,7 @@ myAuthSettings = authSettings; } - - protected CommandResult runCommand(@NotNull MercurialCommandLine cli, @NotNull CommandSettings s) throws VcsException { - s.setPrivateData(getPrivateData()); - return CommandUtil.runCommand(cli, s); - } - + @NotNull protected Set<String> getPrivateData() { String password = myAuthSettings.getPassword(); if (password == null)
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/VersionCommand.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/VersionCommand.java Mon May 26 16:30:19 2014 +0200 @@ -43,7 +43,7 @@ cli.addParameter("version"); cli.addParameter("--quiet"); setDefaultLocale(cli); - CommandResult result = CommandUtil.runCommand(cli, myCommandSettings); + CommandResult result = runCommand(cli, myCommandSettings); return HgVersion.parse(result.getStdout()); }
--- a/mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSubrepoUsageStatistics.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSubrepoUsageStatistics.java Mon May 26 16:30:19 2014 +0200 @@ -16,29 +16,30 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; +import jetbrains.buildServer.usageStatistics.impl.providers.BaseVCSFeatureUsageStatisticsProvider; import jetbrains.buildServer.vcs.SVcsRoot; import jetbrains.buildServer.vcs.VcsManager; import org.jetbrains.annotations.NotNull; -public class MercurialSubrepoUsageStatistics /*extends BaseVCSFeatureUsageStatisticsProvider*/ { +public class MercurialSubrepoUsageStatistics extends BaseVCSFeatureUsageStatisticsProvider { public MercurialSubrepoUsageStatistics(@NotNull VcsManager vcsManager) { -// super(vcsManager); + super(vcsManager); } @NotNull -// @Override + @Override protected String getFeatureName() { return "subRepoSupport-mercurial"; } @NotNull -// @Override + @Override protected String getFeatureDisplayName() { return "Mercurial VCS roots with subrepo support enabled"; } -// @Override + @Override protected boolean hasFeature(@NotNull SVcsRoot root) { return Boolean.parseBoolean(root.getProperty(Constants.DETECT_SUBREPO_CHANGES)); }
--- a/mercurial-server/src/META-INF/build-server-plugin-mercurial.xml Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/META-INF/build-server-plugin-mercurial.xml Mon May 26 16:30:19 2014 +0200 @@ -31,4 +31,9 @@ <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialCommitsInfoBuilderSupport"/> <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialModificationInfoBuilder"/> + + <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl"/> + <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver"/> + + <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialFetchService"/> </beans>
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgTestConnectionSupport.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgTestConnectionSupport.java Mon May 26 16:30:19 2014 +0200 @@ -47,8 +47,8 @@ public String testConnection(@NotNull VcsRoot vcsRoot) throws VcsException { - HgVcsRoot root = myHgVcsRootFactory.createHgRoot(vcsRoot); - HgRepo repo = createRepo(root); + final HgVcsRoot root = myHgVcsRootFactory.createHgRoot(vcsRoot); + final HgRepo repo = createRepo(root); try { repo.id().repository(root.getRepository()) .withAuthSettings(root.getAuthSettings()) @@ -64,8 +64,9 @@ return new VcsException("Cannot find mercurial executable at path '" + myHgPathProvider.getHgPath(root) + "'", e); } - private ServerHgRepo createRepo(HgVcsRoot root) throws VcsException { - return myRepoFactory.create(getWorkingDir(root), myHgPathProvider.getHgPath(root), root.getAuthSettings()); + @NotNull + private HgRepo createRepo(HgVcsRoot root) throws VcsException { + return myRepoFactory.createRepo(root, getWorkingDir(root)); } private File getWorkingDir(HgVcsRoot root) {
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java Mon May 26 16:30:19 2014 +0200 @@ -61,11 +61,12 @@ @NotNull public RepositoryStateData getCurrentState(@NotNull VcsRoot root) throws VcsException { final HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); - Map<String, String> revisions = myVcs.syncRepository(hgRoot, new VcsCallable<Map<String, String>>() { + VcsCallable<Map<String, String>> cmd = new VcsCallable<Map<String, String>>() { public Map<String, String> call() throws VcsException { return getHeads(hgRoot); } - }); + }; + Map<String, String> revisions = myVcs.syncRepository(hgRoot, new SyncSettings<Map<String, String>>(cmd)); String defaultBranchName = hgRoot.getBranchName(); if (revisions.get(defaultBranchName) == null) { throw new VcsException("Cannot find revision of the default branch '" +
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCommitsInfoBuilderSupport.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCommitsInfoBuilderSupport.java Mon May 26 16:30:19 2014 +0200 @@ -59,11 +59,12 @@ final HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); final ServerHgRepo repo = mySupport.createRepo(hgRoot); - final MultiMapToList<String, String> heads = mySupport.syncRepository(hgRoot, new VcsCallable<MultiMapToList<String, String>>() { + VcsCallable<MultiMapToList<String, String>> cmd = new VcsCallable<MultiMapToList<String, String>>() { public MultiMapToList<String, String> call() throws VcsException { return commitToBranchs(mySupport.getCollectChangesPolicy().getHeads(hgRoot)); } - }); + }; + final MultiMapToList<String, String> heads = mySupport.syncRepository(hgRoot, new SyncSettings<MultiMapToList<String, String>>(cmd)); repo.logSubstates().call(new CommitsAndMountPointsCommand.Callback() { private final MercurialCommitsInfoBuilderStates subs = new MercurialCommitsInfoBuilderStates();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialFetchService.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2014 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; + +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ProgressParser; +import jetbrains.buildServer.vcs.CheckoutRules; +import jetbrains.buildServer.vcs.FetchService; +import jetbrains.buildServer.vcs.VcsException; +import jetbrains.buildServer.vcs.VcsRoot; +import org.jetbrains.annotations.NotNull; + +public class MercurialFetchService implements FetchService, MercurialServerExtension { + + private final MercurialVcsSupport myVcs; + private final HgVcsRootFactory myHgVcsRootFactory; + + public MercurialFetchService(@NotNull MercurialVcsSupport vcs, + @NotNull HgVcsRootFactory hgVcsRootFactory) { + myVcs = vcs; + myHgVcsRootFactory = hgVcsRootFactory; + vcs.addExtension(this); + } + + public void fetchRepository(@NotNull VcsRoot root, + @NotNull CheckoutRules rules, + @NotNull FetchRepositoryCallback callback) throws VcsException { + SyncSettings<Void> settings = new SyncSettings<Void>(VcsCallable.NO_OP); + settings.setProgressConsumer(new FetchProgressConsumer(callback)); + myVcs.syncRepository(myHgVcsRootFactory.createHgRoot(root)); + } + + private class FetchProgressConsumer implements ProgressParser.ProgressConsumer { + private final FetchRepositoryCallback myCallback; + private FetchProgressConsumer(@NotNull FetchRepositoryCallback callback) { + myCallback = callback; + } + + public void consume(float progress, @NotNull String stage) { + myCallback.update(progress, stage); + } + } +}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Mon May 26 16:30:19 2014 +0200 @@ -123,7 +123,7 @@ @NotNull public byte[] getContent(@NotNull final String filePath, @NotNull final VcsRoot vcsRoot, @NotNull final String version) throws VcsException { ChangeSet cset = new ChangeSet(version); - HgVcsRoot root = myHgVcsRootFactory.createHgRoot(vcsRoot); + HgVcsRoot root = getHgRoot(vcsRoot); syncRepository(root, cset); HgRepo repo = createRepo(root); File parentDir = repo.cat().files(filePath).atRevision(cset).call(); @@ -138,6 +138,11 @@ } @NotNull + public HgVcsRoot getHgRoot(@NotNull final VcsRoot vcsRoot) throws VcsException { + return myHgVcsRootFactory.createHgRoot(vcsRoot); + } + + @NotNull public String getName() { return Constants.VCS_NAME; } @@ -174,11 +179,12 @@ } @NotNull - public String describeVcsRoot(final VcsRoot vcsRoot) { + public String describeVcsRoot(@NotNull final VcsRoot vcsRoot) { return "mercurial: " + vcsRoot.getProperty(Constants.REPOSITORY_PROP); } @Override + @NotNull public TestConnectionSupport getTestConnectionSupport() { return myTestConnection; } @@ -227,21 +233,28 @@ } } - File parentDir = repo.cat().files(notDeletedFiles).atRevision(toVer).call(); + File parentDir = null; try { - for (FileStatus f: modifiedFiles) { - String mappedPath = checkoutRules.map(f.getPath()); - if (mappedPath == null) continue; // skip - final File virtualFile = new File(mappedPath); - if (f.getStatus() == Status.REMOVED) { - builder.deleteFile(virtualFile, true); - } else { - File realFile = new File(parentDir, f.getPath()); - FileInputStream is = new FileInputStream(realFile); - try { - builder.changeOrCreateBinaryFile(virtualFile, null, is, realFile.length()); - } finally { - is.close(); + if (root.useArchiveForPatch()) { + parentDir = HgFileUtil.createTempDir(); + File archFile = new File(parentDir, "arch.tar"); + buildIncrementalPatchWithArchive(builder, repo, toVer, checkoutRules, modifiedFiles, notDeletedFiles, archFile); + } else { + parentDir = repo.cat().files(notDeletedFiles).atRevision(toVer).call(); + for (FileStatus f: modifiedFiles) { + String mappedPath = checkoutRules.map(f.getPath()); + if (mappedPath == null) continue; // skip + final File virtualFile = new File(mappedPath); + if (f.getStatus() == Status.REMOVED) { + builder.deleteFile(virtualFile, true); + } else { + File realFile = new File(parentDir, f.getPath()); + FileInputStream is = new FileInputStream(realFile); + try { + builder.changeOrCreateBinaryFile(virtualFile, null, is, realFile.length()); + } finally { + is.close(); + } } } } @@ -253,7 +266,50 @@ builder.deleteDirectory(new File(""), true);//clean patch buildFullPatch(root, toVer, builder, checkoutRules); } finally { - deleteDir(parentDir, Loggers.VCS); + if (parentDir != null) + deleteDir(parentDir, Loggers.VCS); + } + } + + private void buildIncrementalPatchWithArchive(@NotNull PatchBuilder builder, + @NotNull HgRepo repo, + @NotNull ChangeSet toVer, + @NotNull CheckoutRules checkoutRules, + @NotNull List<FileStatus> modifiedFiles, + @NotNull List<String> notDeletedFiles, + @NotNull File archiveFile) throws VcsException, IOException { + ArchiveCommand archive = repo.archive().revision(toVer).type("tar").destination(archiveFile); + int i = 0; + while (i < notDeletedFiles.size()) { + String mappedPath = checkoutRules.map(notDeletedFiles.get(i)); + if (mappedPath == null) { + i++; + continue; + } + if (archive.addIncludeRule(notDeletedFiles.get(i))) { + i++; + continue; + } + //archive command is full, call it + archive.call(); + buildPatchFromArchive(builder, archiveFile, checkoutRules, new ExcludeHgArchival()); + FileUtil.delete(archiveFile); + archive = repo.archive().revision(toVer).type("tar").destination(archiveFile); + } + if (!notDeletedFiles.isEmpty()) { + archive.call(); + buildPatchFromArchive(builder, archiveFile, checkoutRules, new ExcludeHgArchival()); + FileUtil.delete(archiveFile); + } + + //delete removed files + for (FileStatus f: modifiedFiles) { + if (f.getStatus() == Status.REMOVED) { + String mappedPath = checkoutRules.map(f.getPath()); + if (mappedPath == null) + continue; // skip + builder.deleteFile(new File(mappedPath), true); + } } } @@ -338,11 +394,7 @@ if (root.useArchiveForPatch()) { File archive = new File(tempDir, "arch.tar"); repo.archive().revision(toVer).type("tar").destination(archive).call(); - buildPatchFromArchive(builder, archive, checkoutRules, new FileFilter() { - public boolean accept(File f) { - return !f.getName().equals(".hg_archival.txt"); - } - }); + buildPatchFromArchive(builder, archive, checkoutRules, new ExcludeHgArchival()); } else { repo.archive().revision(toVer).destination(tempDir).call(); buildPatchFromDirectory(builder, tempDir, checkoutRules, myAcceptAllFilter); @@ -353,11 +405,7 @@ if (root.useArchiveForPatch()) { File archive = new File(tempDir, "arch.tar"); repo.archive().revision(toVer).type("tar").destination(archive).call(); - buildPatchFromArchive(builder, archive, checkoutRules, new FileFilter() { - public boolean accept(File f) { - return !f.getName().equals(".hg_archival.txt"); - } - }); + buildPatchFromArchive(builder, archive, checkoutRules, new ExcludeHgArchival()); } else { repo.archive().revision(toVer).destination(tempDir).call(); buildPatchFromDirectory(builder, tempDir, checkoutRules, myAcceptAllFilter); @@ -490,21 +538,21 @@ } public void syncRepository(@NotNull final VcsRoot root) throws VcsException { - syncRepository(myHgVcsRootFactory.createHgRoot(root)); + syncRepository(getHgRoot(root)); } public void syncRepository(@NotNull final HgVcsRoot root) throws VcsException { - syncRepository(root, VcsCallable.NO_OP); + syncRepository(root, new SyncSettings<Void>(VcsCallable.NO_OP)); } - public <T> T syncRepository(@NotNull HgVcsRoot root, @NotNull VcsCallable<T> cmd) throws VcsException { + public <T> T syncRepository(@NotNull HgVcsRoot root, @NotNull SyncSettings<T> settings) throws VcsException { boolean customWorkingDir = root.getCustomWorkingDir() != null; File workingDir = getWorkingDir(root); int attemptsLeft = 3; VcsException lastError = null; while (attemptsLeft-- > 0) { try { - return syncRepositoryOnce(root, cmd, workingDir); + return syncRepositoryOnce(root, settings, workingDir); } catch (UnrelatedRepositoryException e) { if (customWorkingDir) throw new VcsException(e.getMessage() + ". VCS root uses a custom clone dir, manual recovery is required.", e); @@ -525,7 +573,7 @@ } - private <T> T syncRepositoryOnce(@NotNull HgVcsRoot root, @NotNull VcsCallable<T> cmd, @NotNull File workingDir) throws VcsException { + private <T> T syncRepositoryOnce(@NotNull HgVcsRoot root, @NotNull SyncSettings<T> settings, @NotNull File workingDir) throws VcsException { lockWorkDir(workingDir); HgRepo repo = createRepo(root); try { @@ -533,15 +581,17 @@ resetBookmarks(repo); repo.pull().fromRepository(root.getRepository()) .withTimeout(myConfig.getPullTimeout()) + .withProgressConsumer(settings.getProgressConsumer()) .call(); } else { repo.doClone().fromRepository(root.getRepository()) .setUpdateWorkingDir(false) .useUncompressedTransfer(root.isUncompressedTransfer()) + .withProgressConsumer(settings.getProgressConsumer()) .call(); repo.setDefaultPath(root.getRepository()); } - return cmd.call(); + return settings.getCmd().call(); } finally { unlockWorkDir(workingDir); } @@ -578,7 +628,7 @@ } public void buildPatch(@NotNull VcsRoot root, @Nullable String fromVersion, @NotNull String toVersion, @NotNull PatchBuilder builder, @NotNull CheckoutRules checkoutRules) throws IOException, VcsException { - HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); + HgVcsRoot hgRoot = getHgRoot(root); buildPatch(hgRoot, fromVersion, toVersion, builder, checkoutRules); } @@ -621,11 +671,12 @@ return myConfig.allowSourceCaching(); } + @NotNull public String label(@NotNull String label, @NotNull String version, @NotNull VcsRoot root, @NotNull CheckoutRules checkoutRules) throws VcsException { File tmpDir = null; try { tmpDir = createLabelingTmpDir(); - HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); + HgVcsRoot hgRoot = getHgRoot(root); hgRoot.setCustomWorkingDir(tmpDir); syncRepository(hgRoot); HgRepo repo = createRepo(hgRoot); @@ -660,7 +711,7 @@ return label.replace(':', '_').replace('\r', '_').replace('\n', '_'); } - public File getWorkingDir(@NotNull HgVcsRoot root) { + public File getWorkingDir(HgVcsRoot root) { File customDir = root.getCustomWorkingDir(); return customDir != null ? customDir : myMirrorManager.getMirrorDir(root.getRepository()); } @@ -703,17 +754,19 @@ } } + @NotNull public ServerHgRepo createRepo(@NotNull HgVcsRoot root) throws VcsException { - return myRepoFactory.create(getWorkingDir(root), myHgPathProvider.getHgPath(root), root.getAuthSettings()); + return myRepoFactory.createRepo(root, getWorkingDir(root)); } + @NotNull public ServerHgRepo createRepo(@NotNull OperationContext ctx, @NotNull HgVcsRoot root) throws VcsException { - return ctx.createRepo(getWorkingDir(root), myHgPathProvider.getHgPath(root), root.getAuthSettings()); + return ctx.createRepo(root, getWorkingDir(root)); } - - public HgRepo createRepo(@NotNull HgVcsRoot root, @NotNull File customDir) throws VcsException { - return myRepoFactory.create(customDir, myHgPathProvider.getHgPath(root), root.getAuthSettings()); + @NotNull + public ServerHgRepo createRepo(@NotNull HgVcsRoot root, @NotNull File customDir) throws VcsException { + return myRepoFactory.createRepo(root, customDir); } @NotNull @@ -746,4 +799,11 @@ } return super.getVcsCustomExtension(extensionClass); } + + + private static class ExcludeHgArchival implements FileFilter { + public boolean accept(File f) { + return !f.getName().equals(".hg_archival.txt"); + } + } }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/OperationContext.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/OperationContext.java Mon May 26 16:30:19 2014 +0200 @@ -18,10 +18,10 @@ import com.intellij.openapi.util.Pair; import gnu.trove.TLongObjectHashMap; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; import jetbrains.buildServer.util.Hash; -import jetbrains.buildServer.util.graph.*; +import jetbrains.buildServer.util.graph.BFSVisitorAdapter; +import jetbrains.buildServer.util.graph.DAG; import jetbrains.buildServer.vcs.ModificationData; import jetbrains.buildServer.vcs.RepositoryStateData; import jetbrains.buildServer.vcs.VcsException; @@ -117,11 +117,13 @@ } @NotNull - public ServerHgRepo createRepo(@NotNull File workingDir, @NotNull String hgPath, @NotNull AuthSettings authSettings) throws VcsException { + public ServerHgRepo createRepo(@NotNull final HgVcsRoot root, @NotNull final File workingDir) throws VcsException { ServerHgRepo repo = myRepos.get(workingDir); - if (repo != null) + if (repo != null) { return repo; - repo = myRepoFactory.create(workingDir, hgPath, authSettings); + } + + repo = myRepoFactory.createRepo(root, workingDir); repo.setOperationContext(this); myRepos.put(workingDir, repo); return repo; @@ -208,7 +210,7 @@ @NotNull String fromRevision, @NotNull String toRevision) throws VcsException { syncRepository(root); - ServerHgRepo repo = createRepo(myVcs.getWorkingDir(root), myHgPathProvider.getHgPath(root), root.getAuthSettings()); + ServerHgRepo repo = createRepo(root, myVcs.getWorkingDir(root)); if (!repo.supportRevsets()) return singleton(fromRevision);
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RepoFactory.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RepoFactory.java Mon May 26 16:30:19 2014 +0200 @@ -18,33 +18,26 @@ import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsFactory; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRoot; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; -import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; -import static com.intellij.openapi.util.io.FileUtil.createTempFile; -import static com.intellij.openapi.util.io.FileUtil.delete; - /** * @author dmitry.neverov */ public class RepoFactory implements HgRepoFactory { protected final ServerPluginConfig myConfig; - protected final CommandSettingsFactory myCommandSettingsFactory; + protected final CommandSettingsForRoot myCommandSettingsFactory; protected final HgPathProvider myHgPathProvider; - protected final MercurialLogTemplate myLogTemplate = new MercurialLogTemplate("/buildServerResources/log.template", "hg.log.template"); - protected final MercurialLogTemplate myLogNoFilesTemplate = new MercurialLogTemplate("/buildServerResources/log.no.files.template", "hg.short.log.template"); - protected final MercurialLogTemplate myDagTemplate = new MercurialLogTemplate("/buildServerResources/dag.template", "hg.dag.template"); - protected final MercurialLogTemplate myFastLogTemplate = new MercurialLogTemplate("/buildServerResources/fastlog.template", "hg.fastlog.template"); public RepoFactory(@NotNull ServerPluginConfig config, - @NotNull CommandSettingsFactory commandSettingsFactory, + @NotNull CommandSettingsForRoot commandSettingsFactory, @NotNull HgPathProvider hgPathProvider) throws IOException { myConfig = config; myCommandSettingsFactory = commandSettingsFactory; @@ -52,58 +45,20 @@ } @NotNull - public ServerHgRepo create(@NotNull File workingDir, - @NotNull String hgPath, - @NotNull AuthSettings authSettings) throws VcsException { - return new ServerHgRepo(myCommandSettingsFactory, myConfig, workingDir, hgPath, authSettings) - .withLogTemplates(myLogTemplate.getTemplate(), - myLogNoFilesTemplate.getTemplate(), - myDagTemplate.getTemplate(), - myFastLogTemplate.getTemplate()); + protected ServerHgRepo create(@NotNull File workingDir, + @NotNull String hgPath, + @NotNull AuthSettings authSettings, + @NotNull CommandSettingsFactory commandSettingsFactory, + @NotNull ServerPluginConfig config) { + return new ServerHgRepo(commandSettingsFactory, config, workingDir, hgPath, authSettings); } - public HgRepo createRepo(@NotNull HgVcsRoot root, @NotNull File workingDir) throws VcsException { - return create(workingDir, myHgPathProvider.getHgPath(root), root.getAuthSettings()); + @NotNull + public ServerHgRepo createRepo(@NotNull HgVcsRoot root, @NotNull File workingDir) throws VcsException { + return create(workingDir, myHgPathProvider.getHgPath(root), root.getAuthSettings(), myCommandSettingsFactory.forRoot(root), myConfig); } public void dispose() { - myLogTemplate.dispose(); - myLogNoFilesTemplate.dispose(); - myDagTemplate.dispose(); - myFastLogTemplate.dispose(); } - static class MercurialLogTemplate { - private final String myResourcePath; - private final String myTmpFileSuffix; - private File myFile; - - private MercurialLogTemplate(@NotNull String resourcePath, @NotNull String tmpFileSuffix) throws IOException { - myResourcePath = resourcePath; - myTmpFileSuffix = tmpFileSuffix; - copyTemplate(); - } - - @NotNull - public File getTemplate() throws VcsException { - if (myFile.isFile() && myFile.exists()) - return myFile; - try { - copyTemplate(); - return myFile; - } catch (IOException e) { - throw new VcsException("Cannot create mercurial log template", e); - } - } - - public void dispose() { - delete(myFile); - } - - private void copyTemplate() throws IOException { - File template = createTempFile("teamcity", myTmpFileSuffix); - FileUtil.copyResource(RepoFactory.class, myResourcePath, template); - myFile = template; - } - } }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerCommandSettingsFactory.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerCommandSettingsFactory.java Mon May 26 16:30:19 2014 +0200 @@ -28,6 +28,7 @@ myConfig = config; } + @NotNull public CommandSettings create() { return new CommandSettings().setLogLevel("debug").setLogOutputLimit(myConfig.getLogOutputLimit()); }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java Mon May 26 16:30:19 2014 +0200 @@ -39,10 +39,10 @@ private final static HgVersion REVSET_HG_VERSION = new HgVersion(1, 7, 0); private final CommandSettingsFactory myCommandSettingsFactory; private final ServerPluginConfig myConfig; - private File myLogTemplate; - private File myLogNoFilesTemplate; - private File myDagTemplate; - private File myFastLogTemplate; + protected final MercurialClasspathTemplate myLogTemplate = new MercurialClasspathTemplate("/buildServerResources/log.template", "hg.log.template"); + protected final MercurialClasspathTemplate myLogNoFilesTemplate = new MercurialClasspathTemplate("/buildServerResources/log.no.files.template", "hg.short.log.template"); + protected final MercurialClasspathTemplate myDagTemplate = new MercurialClasspathTemplate("/buildServerResources/dag.template", "hg.dag.template"); + protected final MercurialClasspathTemplate myFastLogTemplate = new MercurialClasspathTemplate("/buildServerResources/fastlog.template", "hg.fastlog.template"); private OperationContext myContext; public ServerHgRepo(@NotNull CommandSettingsFactory commandSettingsFactory, @@ -59,17 +59,6 @@ myContext = context; } - public ServerHgRepo withLogTemplates(@NotNull File logTemplate, - @NotNull File logNoFilesTemplate, - @NotNull File dagTemplate, - @NotNull File fastLogTemplate) { - myLogTemplate = logTemplate; - myLogNoFilesTemplate = logNoFilesTemplate; - myDagTemplate = dagTemplate; - myFastLogTemplate = fastLogTemplate; - return this; - } - public LogCommand log() { return new LogCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings).withTemplate(myLogTemplate); } @@ -80,7 +69,7 @@ } public LogCommand log(@NotNull HgVcsRoot root) { - File template = root.isSubrepo() && !myConfig.reportSubrepoChangesFileStatus() ? myFastLogTemplate : myLogTemplate; + final MercurialTemplate template = root.isSubrepo() && !myConfig.reportSubrepoChangesFileStatus() ? myFastLogTemplate : myLogTemplate; return new LogCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings).withTemplate(template); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SyncSettings.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2014 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; + +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ProgressParser; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SyncSettings<T> { + private VcsCallable<T> myCmd; + private ProgressParser.ProgressConsumer myProgressConsumer; + + public SyncSettings(@NotNull VcsCallable<T> cmd) { + myCmd = cmd; + } + + @NotNull + public VcsCallable<T> getCmd() { + return myCmd; + } + + @Nullable + public ProgressParser.ProgressConsumer getProgressConsumer() { + return myProgressConsumer; + } + + @NotNull + public SyncSettings<T> setProgressConsumer(ProgressParser.ProgressConsumer progressConsumer) { + myProgressConsumer = progressConsumer; + return this; + } +}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesNoRevsets.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesNoRevsets.java Mon May 26 16:30:19 2014 +0200 @@ -17,6 +17,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; import com.intellij.openapi.util.Pair; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialTemplate; import jetbrains.buildServer.buildTriggers.vcs.mercurial.ServerHgRepo; import jetbrains.buildServer.util.graph.DAG; import jetbrains.buildServer.util.graph.DAGIterator; @@ -24,7 +25,6 @@ import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; -import java.io.File; import java.util.*; /** @@ -34,9 +34,9 @@ private final HgVcsRoot myRoot; private final ServerHgRepo myRepo; - private final File myLogNoFilesTemplate; + private final MercurialTemplate myLogNoFilesTemplate; - public CollectChangesNoRevsets(@NotNull HgVcsRoot root, @NotNull ServerHgRepo repo, @NotNull File logNoFilesTemplate) { + public CollectChangesNoRevsets(@NotNull HgVcsRoot root, @NotNull ServerHgRepo repo, @NotNull MercurialTemplate logNoFilesTemplate) { myRoot = root; myRepo = repo; myLogNoFilesTemplate = logNoFilesTemplate;
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentMirrorCleanerTest.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentMirrorCleanerTest.java Mon May 26 16:30:19 2014 +0200 @@ -17,6 +17,8 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; import jetbrains.buildServer.agent.*; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory; import jetbrains.buildServer.vcs.*; import jetbrains.buildServer.vcs.impl.VcsRootImpl; @@ -62,7 +64,7 @@ AgentPluginConfigImpl pluginConfig = new AgentPluginConfigImpl(agentConfig); myMirrorManager = new MirrorManagerImpl(pluginConfig); - AgentRepoFactory repoFactory = new AgentRepoFactory(new TestCommandSettingsFactory(), new AgentHgPathProvider(agentConfig)); + AgentRepoFactory repoFactory = new AgentRepoFactory(new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver()), new AgentHgPathProvider(agentConfig)); myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig, myMirrorManager, repoFactory); myCleaner = new AgentMirrorCleaner(myMirrorManager); myLogger = myContext.mock(BuildProgressLogger.class);
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java Mon May 26 16:30:19 2014 +0200 @@ -18,6 +18,8 @@ import jetbrains.buildServer.agent.AgentRunningBuild; import jetbrains.buildServer.agent.BuildAgentConfiguration; import jetbrains.buildServer.agent.BuildProgressLogger; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory; import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.util.TestFor; @@ -75,7 +77,7 @@ final AgentPluginConfigImpl pluginConfig = new AgentPluginConfigImpl(agentConfig); myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig, new MirrorManagerImpl(pluginConfig), - new AgentRepoFactory(new TestCommandSettingsFactory(), new AgentHgPathProvider(agentConfig))); + new AgentRepoFactory(new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver()), new AgentHgPathProvider(agentConfig))); myLogger = myContext.mock(BuildProgressLogger.class); myContext.checking(new Expectations() {{
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSubreposTest.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSubreposTest.java Mon May 26 16:30:19 2014 +0200 @@ -21,6 +21,8 @@ import jetbrains.buildServer.agent.BuildProgressLogger; import jetbrains.buildServer.agent.vcs.UpdateByIncludeRules2; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.ConnectionRefusedException; import jetbrains.buildServer.util.FileUtil; @@ -83,7 +85,7 @@ myMirrorManager = new MirrorManagerImpl(pluginConfig); myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig, myMirrorManager, - new AgentRepoFactory(new TestCommandSettingsFactory(), new AgentHgPathProvider(agentConfig))); + new AgentRepoFactory(new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver()), new AgentHgPathProvider(agentConfig))); myLogger = myContext.mock(BuildProgressLogger.class); myContext.checking(new Expectations() {{
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ExtensionsTest.java Mon May 26 16:30:19 2014 +0200 @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2014 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; + +import jetbrains.buildServer.vcs.VcsException; +import jetbrains.buildServer.vcs.VcsRoot; +import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; + +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.ServerPluginConfigBuilder.serverPluginConfig; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot; + +/** + * Created 25.02.14 13:17 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +@RequiredHgVersion(min = "2.0.0") +public class ExtensionsTest extends BaseMercurialTestCase { + + @Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion") + public void test_no_extension(HgVersion _) throws IOException, VcsException { + String extension = "HGExtensionThatDoesNotExits"; + + try { + runWithExtensions(extension); + Assert.fail(); + } catch (VcsException e) { + Assert.assertTrue(e.getMessage().contains(extension)); + } + } + + @Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion") + public void test_extension(HgVersion _) throws IOException, VcsException { + runWithExtensions("mq", "largefiles"); + } + + private void runWithExtensions(@NotNull String... extensions) throws IOException, VcsException { + ServerPluginConfig config = serverPluginConfig() + .cachesDir(myTempFiles.createTempDir()) + .hgPath(Util.getHgPath()) + .build(); + + final File myRemoteRepository = myTempFiles.createTempDir(); + Util.copyRepository(new File("mercurial-tests/testData/rep2"), myRemoteRepository); + + + final MercurialSupportBuilder hgBuilder = mercurialSupport().withConfig(config); + final MercurialVcsSupport vcs = hgBuilder.build(); + final VcsRoot root = vcsRoot().withUrl(myRemoteRepository.getAbsolutePath()).withBranch("default").withExtensions(extensions).build(); + + vcs.getCollectChangesPolicy().getCurrentState(root); + vcs.getTestConnectionSupport().testConnection(root); + } + + +}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java Mon May 26 16:30:19 2014 +0200 @@ -16,6 +16,8 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory; import jetbrains.buildServer.serverSide.ServerListener; import jetbrains.buildServer.util.EventDispatcher; @@ -52,7 +54,7 @@ MirrorManagerImpl mirrorManager = new MirrorManagerImpl(myConfig); myHgPathProvider = new ServerHgPathProvider(myConfig); if (myRepoFactory == null) - myRepoFactory = new RepoFactory(myConfig, new TestCommandSettingsFactory(), myHgPathProvider); + myRepoFactory = new RepoFactory(myConfig, new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver()), myHgPathProvider); HgTestConnectionSupport testConnection = new HgTestConnectionSupport(myHgRootFactory, myRepoFactory, mirrorManager, myHgPathProvider); final ResetCacheRegister resetCacheManager = myContext.mock(ResetCacheRegister.class); myContext.checking(new Expectations() {{
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java Mon May 26 16:30:19 2014 +0200 @@ -601,8 +601,6 @@ if (!SystemInfo.isUnix) return; - RepoFactory repoFactory = new RepoFactory(myPluginConfig, new TestCommandSettingsFactory(), myHgPathProvider); - //create a file on the server File dirOnTheServer = myTempFiles.createTempDir(); File fileOnTheServer = new File(dirOnTheServer, "file.on.server"); @@ -610,7 +608,7 @@ //create a remote repository with symlink pointing to the file on the server File repository = copyRepository(myTempFiles, simpleRepo()); - ServerHgRepo repo = repoFactory.create(repository, getHgPath(), new AuthSettings()); + ServerHgRepo repo = new ServerHgRepo(new TestCommandSettingsFactory(), myPluginConfig, repository, getHgPath(), new AuthSettings()); repo.update().toRevision("9c6a6b4aede0").call(); new ProcessBuilder("ln", "-s", dirOnTheServer.getCanonicalPath()).directory(repository).start().waitFor(); new ProcessBuilder(getHgPath(), "add", dirOnTheServer.getName()).directory(repository).start().waitFor();
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubrepoChangesTest.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubrepoChangesTest.java Mon May 26 16:30:19 2014 +0200 @@ -16,10 +16,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CatCommand; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsFactory; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*; import jetbrains.buildServer.vcs.*; import org.jetbrains.annotations.NotNull; import org.testng.annotations.BeforeMethod; @@ -230,15 +227,11 @@ .build(); final AtomicInteger catCallCounter = new AtomicInteger(0); - RepoFactory repoFactory = new RepoFactory(pluginConfig, new TestCommandSettingsFactory(), myHgPathProvider) { + RepoFactory repoFactory = new RepoFactory(pluginConfig, new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver()), myHgPathProvider) { @NotNull @Override - public ServerHgRepo create(@NotNull File workingDir, @NotNull String hgPath, @NotNull AuthSettings authSettings) throws VcsException { - return new CountingServerHgRepo(myCommandSettingsFactory, myConfig, workingDir, hgPath, authSettings, catCallCounter) - .withLogTemplates(myLogTemplate.getTemplate(), - myLogNoFilesTemplate.getTemplate(), - myDagTemplate.getTemplate(), - myFastLogTemplate.getTemplate()); + protected ServerHgRepo create(@NotNull File workingDir, @NotNull String hgPath, @NotNull AuthSettings authSettings, @NotNull CommandSettingsFactory commandSettingsFactory, @NotNull ServerPluginConfig config) { + return new CountingServerHgRepo(commandSettingsFactory, config, workingDir, hgPath, authSettings, catCallCounter); } };
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java Mon May 26 16:30:19 2014 +0200 @@ -16,6 +16,7 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial; +import jetbrains.buildServer.util.StringUtil; import jetbrains.buildServer.vcs.SVcsRoot; import jetbrains.buildServer.vcs.impl.VcsRootImpl; import org.jetbrains.annotations.NotNull; @@ -30,6 +31,7 @@ */ public class VcsRootBuilder { + private String myExtensions; private String myRepository; private String myUsername; private String myPassword; @@ -60,6 +62,7 @@ vcsRoot.addProperty(Constants.DETECT_SUBREPO_CHANGES, String.valueOf(myDetectSubrepoChanges)); vcsRoot.addProperty(Constants.INCLUDE_SUBREPOS_IN_PATCH, String.valueOf(myIncludeSubreposInPatch)); vcsRoot.addProperty(Constants.USE_ARCHIVE_FOR_PATCH, String.valueOf(myUseArchiveForPatch)); + vcsRoot.addProperty(Constants.HG_EXTENSIONS, myExtensions); if (myCloneRepositoryTo != null) vcsRoot.addProperty(Constants.SERVER_CLONE_PATH_PROP, String.valueOf(myCloneRepositoryTo.getAbsolutePath())); vcsRoot.addProperty(Constants.USE_TAGS_AS_BRANCHES, String.valueOf(myTagsAsBranches)); @@ -82,6 +85,7 @@ allowing(root).getProperty(with(Constants.USER_FOR_TAG)); will(returnValue(myUserForTag)); allowing(root).getProperty(with(Constants.DETECT_SUBREPO_CHANGES)); will(returnValue(String.valueOf(myDetectSubrepoChanges))); allowing(root).getProperty(with(Constants.USE_TAGS_AS_BRANCHES)); will(returnValue(String.valueOf(myTagsAsBranches))); + allowing(root).getProperty(with(Constants.HG_EXTENSIONS)); will(returnValue(myExtensions)); }}); if (myCloneRepositoryTo != null) { context.checking(new Expectations() {{ @@ -97,6 +101,12 @@ return this; } + @NotNull + public VcsRootBuilder withExtensions(@NotNull String... extensions) { + myExtensions = StringUtil.join(extensions, "\n"); + return this; + } + public VcsRootBuilder withLocalRepository(@NotNull final File repo) { return withUrl(repo.getPath()).withCloneRepositoryTo(repo.getParentFile());
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommandTest.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommandTest.java Mon May 26 16:30:19 2014 +0200 @@ -17,8 +17,8 @@ import jetbrains.buildServer.TempFiles; import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgPathProvider; -import jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialVcsSupport; -import jetbrains.buildServer.util.FileUtil; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialClasspathTemplate; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialTemplate; import jetbrains.buildServer.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.testng.annotations.AfterMethod; @@ -35,7 +35,7 @@ public class LogCommandTest extends BaseCommandTestCase { private TempFiles myTempFiles = new TempFiles(); - private File myTemplateFile; + private MercurialTemplate myTemplateFile; @BeforeMethod @@ -43,8 +43,7 @@ protected void setUp() throws Exception { super.setUp(); setRepository("mercurial-tests/testData/rep1", true); - myTemplateFile = myTempFiles.createTempFile(); - FileUtil.copyResource(MercurialVcsSupport.class, "/buildServerResources/log.template", myTemplateFile); + myTemplateFile = new MercurialClasspathTemplate("/buildServerResources/log.template", "log.template") {}; }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/TestCommandSettingsFactory.java Mon May 26 16:26:58 2014 +0200 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/TestCommandSettingsFactory.java Mon May 26 16:30:19 2014 +0200 @@ -16,8 +16,11 @@ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; +import org.jetbrains.annotations.NotNull; + public class TestCommandSettingsFactory implements CommandSettingsFactory { + @NotNull public CommandSettings create() { return new CommandSettings().addHgEnv("HGRCPATH", ""); }