# HG changeset patch # User Pavel.Sher # Date 1216790283 -14400 # Node ID 7944e8985ebde44af5ce5f56c3aecdb660b2ceaf # Parent de75221eb19671db51078c4872d15f8b4591b974 prepare modules structure for agent side checkout diff -r de75221eb196 -r 7944e8985ebd build.xml --- a/build.xml Mon Jul 21 21:22:25 2008 +0400 +++ b/build.xml Wed Jul 23 09:18:03 2008 +0400 @@ -4,15 +4,18 @@ - + - + + + + diff -r de75221eb196 -r 7944e8985ebd mercurial-agent/mercurial-agent.iml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-agent/mercurial-agent.iml Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff -r de75221eb196 -r 7944e8985ebd mercurial-common/mercurial-common.iml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/mercurial-common.iml Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,21 @@ +/* + * Copyright 2000-2007 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; + +public interface Constants { + String REPOSITORY_PROP = "repositoryPath"; + String HG_COMMAND_PATH_PROP = "hgCommandPath"; +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/PathUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/PathUtil.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2007 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 org.jetbrains.annotations.NotNull; + +public class PathUtil { + @NotNull + public static String normalizeSeparator(@NotNull String repPath) { + return repPath.replace('\\', '/'); + } + } diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CatCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CatCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.util.FileUtil; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +public class CatCommand { + private Settings mySettings; + private String myRevId; + + public CatCommand(@NotNull final Settings settings) { + mySettings = settings; + } + + public void setRevId(final String revId) { + myRevId = revId; + } + + public File execute(List relPaths) throws VcsException { + File tempDir; + try { + tempDir = FileUtil.createTempDirectory("mercurial", "catresult"); + } catch (IOException e) { + throw new VcsException("Unable to create temporary directory"); + } + for (String path: relPaths) { + final File parentFile = new File(tempDir, path).getParentFile(); + if (!parentFile.isDirectory() && !parentFile.mkdirs()) { + throw new VcsException("Failed to create directory: " + parentFile.getAbsolutePath()); + } + } + + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setExePath(mySettings.getHgCommandPath()); + cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); + cli.addParameter("cat"); + cli.addParameter("-o"); + cli.addParameter(tempDir.getAbsolutePath() + File.separator + "%p"); + if (myRevId != null) { + cli.addParameter("-r"); + cli.addParameter(myRevId); + } + for (String p: relPaths) { + cli.addParameter(FileUtil.normalizeSeparator(p)); + } + CommandUtil.runCommand(cli); + return tempDir; + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2007 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; + +import java.util.Date; + +/** + * Represents Mercurial change set + */ +public class ChangeSet { + private int myRevNumber; + @NotNull private String myId; + @NotNull private String myUser; + @NotNull private Date myTimestamp; + private String mySummary; + + public ChangeSet(final int revNumber, @NotNull final String id) { + myRevNumber = revNumber; + myId = id; + } + + /** + * Constructor for version in the form revnum:changeset_id + * @param fullVersion full changeset version as reported by hg log command + */ + public ChangeSet(@NotNull final String fullVersion) { + try { + String[] parts = fullVersion.split(":"); + myRevNumber = Integer.parseInt(parts[0]); + myId = parts[1]; + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + public void setUser(@NotNull final String user) { + myUser = user; + } + + public void setTimestamp(@NotNull final Date timestamp) { + myTimestamp = timestamp; + } + + public void setSummary(final String summary) { + mySummary = summary; + } + + /** + * Returns changeset revision id + * @return changeset revision id + */ + @NotNull + public String getId() { + return myId; + } + + /** + * Returns changeset revision number + * @return changeset revision number + */ + public int getRevNumber() { + return myRevNumber; + } + + /** + * Returns full changeset version as reported by hg log command: revnum:revid + * @return full changeset version as reported by hg log + */ + @NotNull + public String getFullVersion() { + return myRevNumber + ":" + myId; + } + + /** + * Returns user who made changeset + * @return user who made changeset + */ + @NotNull + public String getUser() { + return myUser; + } + + /** + * Returns changeset timestamp + * @return changeset timestamp + */ + @NotNull + public Date getTimestamp() { + return myTimestamp; + } + + /** + * Returns changeset summary specified by user + * @return changeset summary + */ + public String getSummary() { + return mySummary; + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CloneCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CloneCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class CloneCommand { + private Settings mySettings; + private String myDestDir; + private String myToId; + private boolean myUpdateWorkingDir = true; + + public CloneCommand(@NotNull final Settings settings) { + mySettings = settings; + } + + public void setDestDir(@NotNull String destDir) { + myDestDir = destDir; + } + + public void setToId(final String toId) { + myToId = toId; + } + + public void setUpdateWorkingDir(final boolean updateWorkingDir) { + myUpdateWorkingDir = updateWorkingDir; + } + + public void execute() throws VcsException { + if (myDestDir == null) throw new IllegalStateException("Destination dir must be specified"); + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setExePath(mySettings.getHgCommandPath()); + File dir = new File(myDestDir); + File parent = dir.getParentFile(); + cli.setWorkDirectory(parent.getAbsolutePath()); + cli.addParameter("clone"); + if (myToId != null) { + cli.addParameter("-r"); + cli.addParameter(myToId); + } + cli.addParameter("--pull"); + if (!myUpdateWorkingDir) { + cli.addParameter("-U"); + } + cli.addParameter(mySettings.getRepository()); + cli.addParameter(dir.getName()); + + CommandUtil.runCommand(cli); + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.ExecResult; +import jetbrains.buildServer.SimpleCommandLineProcessRunner; +import jetbrains.buildServer.log.Loggers; +import jetbrains.buildServer.util.StringUtil; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +public class CommandUtil { + public static void checkCommandFailed(@NotNull String cmdName, @NotNull ExecResult res) throws VcsException { + if (res.getExitCode() > 0 || res.getException() != null) { + commandFailed(cmdName, res); + } + } + + public static void commandFailed(final String cmdName, final ExecResult res) throws VcsException { + Throwable exception = res.getException(); + String stderr = res.getStderr(); + String stdout = res.getStdout(); + final String message = "'" + cmdName + "' command failed.\n" + + (!StringUtil.isEmpty(stderr) ? "stderr: " + stderr + "\n" : "") + + (!StringUtil.isEmpty(stdout) ? "stdout: " + stdout + "\n" : "") + + (exception != null ? "exception: " + exception.getLocalizedMessage() : ""); + Loggers.VCS.warn(message); + throw new VcsException(message); + } + + public static ExecResult runCommand(@NotNull GeneralCommandLine cli) throws VcsException { + String cmdStr = cli.getCommandLineString(); + Loggers.VCS.debug("Run command: " + cmdStr); + ExecResult res = SimpleCommandLineProcessRunner.runCommand(cli, null); + CommandUtil.checkCommandFailed(cmdStr, res); + return res; + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/IdentifyCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/IdentifyCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.ExecResult; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +/** + * @author Pavel.Sher + * Date: 16.07.2008 + */ +public class IdentifyCommand { + private Settings mySettings; + + public IdentifyCommand(@NotNull final Settings settings) { + mySettings = settings; + } + + public String execute() throws VcsException { + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setExePath(mySettings.getHgCommandPath()); + cli.addParameter("identify"); + cli.addParameter(mySettings.getRepository()); + ExecResult res = CommandUtil.runCommand(cli); + if (res.getStderr().length() > 0) { + CommandUtil.commandFailed(cli.getCommandLineString(), res); + } + return res.getStdout(); + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,122 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.openapi.diagnostic.Logger; +import jetbrains.buildServer.ExecResult; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +public class LogCommand { + private final static Logger LOG = Logger.getInstance(LogCommand.class.getName()); + private String myFromId; + private String myToId; + private Settings mySettings; + private static final String CHANGESET_PREFIX = "changeset:"; + private static final String USER_PREFIX = "user:"; + private static final String DATE_PREFIX = "date:"; + private static final String DATE_FORMAT = "EEE MMM d HH:mm:ss yyyy Z"; + private static final String SUMMARY_PREFIX = "summary:"; + + public LogCommand(@NotNull Settings settings) { + mySettings = settings; + } + + public void setFromRevId(String id) { + myFromId = id; + } + + public void setToRevId(String id) { + myToId = id; + } + + public List execute() throws VcsException { + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setExePath(mySettings.getHgCommandPath()); + cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); + cli.addParameter("log"); + cli.addParameter("-r"); + String from = myFromId; + if (from == null) from = "0"; + String to = myToId; + if (to == null) to = "0"; + cli.addParameter(from + ":" + to); + + ExecResult res = CommandUtil.runCommand(cli); + return parseChangeSets(res.getStdout()); + } + + public static List parseChangeSets(final String stdout) { + List result = new ArrayList(); + String[] lines = stdout.split("\n"); + ChangeSet current = null; + int lineNum = 0; + while (lineNum < lines.length) { + String line = lines[lineNum]; + lineNum++; + + if (line.startsWith(CHANGESET_PREFIX)) { + String revAndId = line.substring(CHANGESET_PREFIX.length()).trim(); + try { + current = new ChangeSet(revAndId); + result.add(current); + } catch (IllegalArgumentException e) { + LOG.warn("Unable to extract changeset id from the line: " + line); + } + + continue; + } + + if (current == null) continue; + + if (line.startsWith(USER_PREFIX)) { + current.setUser(line.substring(USER_PREFIX.length()).trim()); + continue; + } + + if (line.startsWith(DATE_PREFIX)) { + String date = line.substring(DATE_PREFIX.length()).trim(); + try { + Date parsedDate = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH).parse(date); + current.setTimestamp(parsedDate); + } catch (ParseException e) { + LOG.warn("Unable to parse date: " + date); + current = null; + } + + continue; + } + + if (line.startsWith(SUMMARY_PREFIX)) { + String summary = line.substring(SUMMARY_PREFIX.length()).trim(); + current.setSummary(summary); + + continue; + } + } + + return result; + } + +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2007 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; + +/** + * Represents repository modified file + */ +public class ModifiedFile { + /** + * Type of modification + */ + public static enum Status { + ADDED("added"), + MODIFIED("modified"), + REMOVED("removed"), + UNKNOWN("unknown"); + private String myName; + + Status(@NotNull final String name) { + myName = name; + } + + @NotNull + public String getName() { + return myName; + } + } + + @NotNull private Status myStatus; + @NotNull private String myPath; + + public ModifiedFile(@NotNull final Status status, @NotNull final String path) { + myStatus = status; + myPath = path; + } + + /** + * Returns type of modification + * @return type of modification + */ + @NotNull + public Status getStatus() { + return myStatus; + } + + /** + * Returns file path + * @return file path + */ + @NotNull + public String getPath() { + return myPath; + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +/** + * @author Pavel.Sher + * Date: 14.07.2008 + */ +public class PullCommand { + private Settings mySettings; + + public PullCommand(@NotNull final Settings settings) { + mySettings = settings; + } + + public void execute() throws VcsException { + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setExePath(mySettings.getHgCommandPath()); + cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); + cli.addParameter("pull"); + cli.addParameter(mySettings.getRepository()); + CommandUtil.runCommand(cli); + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/Settings.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/Settings.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,102 @@ +/* + * Copyright 2000-2007 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.buildTriggers.vcs.mercurial.PathUtil; +import jetbrains.buildServer.vcs.VcsRoot; +import jetbrains.buildServer.util.Hash; +import jetbrains.buildServer.util.FileUtil; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +/** + * Represents Mercurial repository settings + */ +public class Settings { + private String myRepository; + private String myHgCommandPath; + private File myWorkingDir; + private File myWorkFolderParentDir; + + public Settings(@NotNull File workFolderParentDir, @NotNull VcsRoot vcsRoot) { + myWorkFolderParentDir = workFolderParentDir; + setRepository(vcsRoot.getProperty(Constants.REPOSITORY_PROP)); + setHgCommandPath(vcsRoot.getProperty(Constants.HG_COMMAND_PATH_PROP)); + } + + public Settings() { + } + + public void setRepository(@NotNull final String repository) { + myRepository = repository; + } + + /** + * Returns repository path + * @return repository path + */ + @NotNull + public String getRepository() { + return myRepository; + } + + /** + * Returns path to hg command + * @return path to hg command + */ + @NotNull + public String getHgCommandPath() { + return myHgCommandPath; + } + + public void setHgCommandPath(@NotNull final String hgCommandPath) { + myHgCommandPath = hgCommandPath; + } + + public void setWorkingDir(@NotNull final File workingDir) { + myWorkingDir = FileUtil.getCanonicalFile(workingDir); + } + + /** + * Returns repository working directory where all mercurial commands should be invoked + * @return repository working directory + */ + @NotNull + public File getWorkingDir() { + if (myWorkingDir != null) { + return myWorkingDir; + } + + return getDefaultWorkDir(myWorkFolderParentDir, myRepository); + } + + public static String DEFAULT_WORK_DIR_PREFIX = "hg_"; + + private static File getDefaultWorkDir(@NotNull File workFolderParentDir, @NotNull String repPath) { + String workingDirname = DEFAULT_WORK_DIR_PREFIX + String.valueOf(Hash.calc(normalize(repPath))); + return FileUtil.getCanonicalFile(new File(workFolderParentDir, workingDirname)); + } + + private static String normalize(final String path) { + String normalized = PathUtil.normalizeSeparator(path); + if (path.endsWith("/")) { + return normalized.substring(0, normalized.length()-1); + } + return normalized; + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/StatusCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/StatusCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.ExecResult; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class StatusCommand { + private Settings mySettings; + private String myFromId; + private String myToId; + + public StatusCommand(@NotNull final Settings settings) { + mySettings = settings; + } + + public void setFromRevId(final String fromId) { + myFromId = fromId; + } + + public void setToRevId(final String toId) { + myToId = toId; + } + + public List execute() throws VcsException { + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setExePath(mySettings.getHgCommandPath()); + cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); + cli.addParameter("status"); + cli.addParameter("--rev"); + String from = myFromId; + if (from == null) from = "0"; + String to = myToId; + if (to == null) to = "0"; + cli.addParameter(from + ":" + to); + ExecResult res = CommandUtil.runCommand(cli); + return parseFiles(res.getStdout()); + } + + private List parseFiles(final String stdout) { + List result = new ArrayList(); + String[] lines = stdout.split("\n"); + for (String line: lines) { + if (line.length() == 0) continue; + char modifier = line.charAt(0); + String path = line.substring(2); + ModifiedFile.Status status = toStatus(modifier); + if (status == ModifiedFile.Status.UNKNOWN) continue; + result.add(new ModifiedFile(status, path)); + } + return result; + } + + private ModifiedFile.Status toStatus(final char modifier) { + switch (modifier) { + case 'A': return ModifiedFile.Status.ADDED; + case 'M': return ModifiedFile.Status.MODIFIED; + case 'R': return ModifiedFile.Status.REMOVED; + default: return ModifiedFile.Status.UNKNOWN; + } + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/TipCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/TipCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.ExecResult; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author Pavel.Sher + * Date: 14.07.2008 + */ +public class TipCommand { + @NotNull + private Settings mySettings; + + public TipCommand(@NotNull final Settings settings) { + mySettings = settings; + } + + @NotNull + public ChangeSet execute() throws VcsException { + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); + cli.setExePath(mySettings.getHgCommandPath()); + cli.addParameter("tip"); + ExecResult res = CommandUtil.runCommand(cli); + List changeSets = LogCommand.parseChangeSets(res.getStdout()); + if (changeSets.isEmpty()) { + CommandUtil.commandFailed("hg tip", res); + } + + return changeSets.get(0); + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/UpdateCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/UpdateCommand.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; + +public class UpdateCommand { + private Settings mySettings; + + public UpdateCommand(@NotNull final Settings settings) { + mySettings = settings; + } + + public void execute() throws VcsException { + GeneralCommandLine cli = new GeneralCommandLine(); + cli.setExePath(mySettings.getHgCommandPath()); + cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); + cli.addParameter("update"); + cli.addParameter("-C"); + CommandUtil.runCommand(cli); + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/annotations.jar Binary file mercurial-server/lib/annotations.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/common-api.jar Binary file mercurial-server/lib/common-api.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/log4j-1.2.12.jar Binary file mercurial-server/lib/log4j-1.2.12.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/openapi.jar Binary file mercurial-server/lib/openapi.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/patches-impl.jar Binary file mercurial-server/lib/patches-impl.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/resources_en.jar Binary file mercurial-server/lib/resources_en.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/server-api.jar Binary file mercurial-server/lib/server-api.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/src/openApi-source.jar Binary file mercurial-server/lib/src/openApi-source.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/trove4j.jar Binary file mercurial-server/lib/trove4j.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/lib/util.jar Binary file mercurial-server/lib/util.jar has changed diff -r de75221eb196 -r 7944e8985ebd mercurial-server/mercurial-server.iml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/mercurial-server.iml Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r de75221eb196 -r 7944e8985ebd mercurial-server/resources/buildServerResources/mercurialSettings.jsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/resources/buildServerResources/mercurialSettings.jsp Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,19 @@ +<%@include file="/include.jsp"%> +<%@ taglib prefix="props" tagdir="/WEB-INF/tags/props" %> + + + + + + + + + + + + + + +
+
+
diff -r de75221eb196 -r 7944e8985ebd mercurial-server/src/META-INF/build-server-plugin-mercurial.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/META-INF/build-server-plugin-mercurial.xml Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,6 @@ + + + + + + diff -r de75221eb196 -r 7944e8985ebd mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Wed Jul 23 09:18:03 2008 +0400 @@ -0,0 +1,446 @@ +/* + * Copyright 2000-2007 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.CollectChangesByIncludeRule; +import jetbrains.buildServer.Used; +import jetbrains.buildServer.buildTriggers.vcs.AbstractVcsPropertiesProcessor; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*; +import jetbrains.buildServer.log.Loggers; +import jetbrains.buildServer.serverSide.InvalidProperty; +import jetbrains.buildServer.serverSide.PropertiesProcessor; +import jetbrains.buildServer.serverSide.SBuildServer; +import jetbrains.buildServer.serverSide.ServerPaths; +import jetbrains.buildServer.util.FileUtil; +import jetbrains.buildServer.vcs.*; +import jetbrains.buildServer.vcs.patches.PatchBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Mercurial VCS plugin for TeamCity works as follows: + *
    + *
  • clones repository to internal storage + *
  • before any operation with working copy of repository pulls changes from the original repository + *
  • executes corresponding hg command + *
+ * + *

Working copy of repository is created in the $TEAMCITY_DATA_PATH/system/caches/mercurial folder. + *

Personal builds (remote runs) are not yet supported, they require corresponding functionality from the IDE. + *

Checkout on agent mode is not yet supported too. + */ +public class MercurialVcsSupport extends VcsSupport implements CollectChangesByIncludeRule { + private ServerPaths myServerPaths; + private ConcurrentMap myWorkDirLocks= new ConcurrentHashMap(); + private static final int OLD_WORK_DIRS_CLEANUP_PERIOD = 600; + private VcsManager myVcsManager; + private File myDefaultWorkFolderParent; + + public MercurialVcsSupport(@NotNull final VcsManager vcsManager, + @NotNull ServerPaths paths, + @NotNull SBuildServer server) { + vcsManager.registerVcsSupport(this); + myServerPaths = paths; + myVcsManager = vcsManager; + server.getExecutor().scheduleAtFixedRate(new Runnable() { + public void run() { + removeOldWorkFolders(); + } + }, 0, OLD_WORK_DIRS_CLEANUP_PERIOD, TimeUnit.SECONDS); + myDefaultWorkFolderParent = new File(paths.getCachesDir()); + } + + public List collectBuildChanges(final VcsRoot root, + @NotNull final String fromVersion, + @NotNull final String currentVersion, + final CheckoutRules checkoutRules) throws VcsException { + updateWorkingDirectory(root); + return VcsSupportUtil.collectBuildChanges(root, fromVersion, currentVersion, checkoutRules, this); + } + + public List collectBuildChanges(final VcsRoot root, + final String fromVersion, + final String currentVersion, + final IncludeRule includeRule) throws VcsException { + // first obtain changes between specified versions + List result = new ArrayList(); + Settings settings = new Settings(myDefaultWorkFolderParent, root); + LogCommand lc = new LogCommand(settings); + lc.setFromRevId(new ChangeSet(fromVersion).getId()); + lc.setToRevId(new ChangeSet(currentVersion).getId()); + List changeSets = lc.execute(); + if (changeSets.isEmpty()) { + return result; + } + + // invoke status command for each changeset and determine what files were modified in these changesets + Iterator it = changeSets.iterator(); + ChangeSet prev = it.next(); // skip first changeset (cause it was already reported) + StatusCommand st = new StatusCommand(settings); + while (it.hasNext()) { + ChangeSet cur = it.next(); + st.setFromRevId(prev.getId()); + st.setToRevId(cur.getId()); + List modifiedFiles = st.execute(); + // changeset full version will be set into VcsChange structure and + // stored in database (note that getContent method will be invoked with this version) + List files = toVcsChanges(modifiedFiles, prev.getFullVersion(), cur.getFullVersion(), includeRule); + if (files.isEmpty()) continue; + ModificationData md = new ModificationData(cur.getTimestamp(), files, cur.getSummary(), cur.getUser(), root, cur.getFullVersion(), cur.getFullVersion()); + result.add(md); + prev = cur; + } + + return result; + } + + private List toVcsChanges(final List modifiedFiles, String prevVer, String curVer, final IncludeRule includeRule) { + List files = new ArrayList(); + for (ModifiedFile mf: modifiedFiles) { + String normalizedPath = PathUtil.normalizeSeparator(mf.getPath()); + if (!normalizedPath.startsWith(includeRule.getFrom())) continue; // skip files which do not match include rule + + VcsChangeInfo.Type changeType = getChangeType(mf.getStatus()); + if (changeType == null) { + Loggers.VCS.warn("Unable to convert status: " + mf.getStatus() + " to VCS change type"); + changeType = VcsChangeInfo.Type.NOT_CHANGED; + } + files.add(new VcsChange(changeType, mf.getStatus().getName(), normalizedPath, normalizedPath, prevVer, curVer)); + } + return files; + } + + private VcsChangeInfo.Type getChangeType(final ModifiedFile.Status status) { + switch (status) { + case ADDED:return VcsChangeInfo.Type.ADDED; + case MODIFIED:return VcsChangeInfo.Type.CHANGED; + case REMOVED:return VcsChangeInfo.Type.REMOVED; + } + return null; + } + + @NotNull + public byte[] getContent(final VcsModification vcsModification, + final VcsChangeInfo change, + final VcsChangeInfo.ContentType contentType, + final VcsRoot vcsRoot) throws VcsException { + updateWorkingDirectory(vcsRoot); + String version = contentType == VcsChangeInfo.ContentType.AFTER_CHANGE ? change.getAfterChangeRevisionNumber() : change.getBeforeChangeRevisionNumber(); + return getContent(change.getRelativeFileName(), vcsRoot, version); + } + + @NotNull + public byte[] getContent(final String filePath, final VcsRoot vcsRoot, final String version) throws VcsException { + updateWorkingDirectory(vcsRoot); + Settings settings = new Settings(myDefaultWorkFolderParent, vcsRoot); + CatCommand cc = new CatCommand(settings); + ChangeSet cs = new ChangeSet(version); + cc.setRevId(cs.getId()); + File parentDir = cc.execute(Collections.singletonList(filePath)); + File file = new File(parentDir, filePath); + if (file.isFile()) { + try { + return FileUtil.loadFileBytes(file); + } catch (IOException e) { + throw new VcsException("Failed to load content of file: " + file.getAbsolutePath(), e); + } + } else { + Loggers.VCS.warn("Unable to obtain content of the file: " + filePath); + } + return new byte[0]; + } + + public String getName() { + return "mercurial"; + } + + @Used("jsp") + public String getDisplayName() { + return "Mercurial"; + } + + @Nullable + public PropertiesProcessor getVcsPropertiesProcessor() { + return new AbstractVcsPropertiesProcessor() { + public Collection process(final Map properties) { + List result = new ArrayList(); + if (isEmpty(properties.get(Constants.HG_COMMAND_PATH_PROP))) { + result.add(new InvalidProperty(Constants.HG_COMMAND_PATH_PROP, "Path to 'hg' command must be specified")); + } + if (isEmpty(properties.get(Constants.REPOSITORY_PROP))) { + result.add(new InvalidProperty(Constants.REPOSITORY_PROP, "Repository must be specified")); + } + return result; + } + }; + } + + public String getVcsSettingsJspFilePath() { + return "mercurialSettings.jsp"; + } + + @NotNull + public String getCurrentVersion(final VcsRoot root) throws VcsException { + // we will return full version of the most recent change as current version + updateWorkingDirectory(root); + Settings settings = new Settings(myDefaultWorkFolderParent, root); + TipCommand lc = new TipCommand(settings); + ChangeSet changeSet = lc.execute(); + return changeSet.getFullVersion(); + } + + public String describeVcsRoot(final VcsRoot vcsRoot) { + return "mercurial: " + vcsRoot.getProperty(Constants.REPOSITORY_PROP); + } + + public boolean isTestConnectionSupported() { + return true; + } + + @Nullable + public String testConnection(final VcsRoot vcsRoot) throws VcsException { + Settings settings = new Settings(myDefaultWorkFolderParent, vcsRoot); + IdentifyCommand id = new IdentifyCommand(settings); + StringBuilder res = new StringBuilder(); + res.append(quoteIfNeeded(settings.getHgCommandPath())); + res.append(" identify "); + res.append(quoteIfNeeded(settings.getRepository())); + res.append('\n').append(id.execute()); + return res.toString(); + } + + private String quoteIfNeeded(@NotNull String str) { + if (str.indexOf(' ') != -1) { + return "\"" + str + "\""; + } + + return str; + } + + @Nullable + public Map getDefaultVcsProperties() { + return Collections.singletonMap(Constants.HG_COMMAND_PATH_PROP, "hg"); + } + + public String getVersionDisplayName(final String version, final VcsRoot root) throws VcsException { + return version; + } + + @NotNull + public Comparator getVersionComparator() { + // comparator is called when TeamCity needs to sort modifications in the order of their appearance, + // currently we sort changes by revision number, not sure however that this is a good idea, + // probably it would be better to sort them by timestamp (and to add timestamp into the version). + return new Comparator() { + public int compare(final String o1, final String o2) { + try { + return new ChangeSet(o1).getRevNumber() - new ChangeSet(o2).getRevNumber(); + } catch (Exception e) { + return 1; + } + } + }; + } + + public void buildPatch(final VcsRoot root, + @Nullable final String fromVersion, + @NotNull final String toVersion, + final PatchBuilder builder, + final CheckoutRules checkoutRules) throws IOException, VcsException { + updateWorkingDirectory(root); + Settings settings = new Settings(myDefaultWorkFolderParent, root); + if (fromVersion == null) { + buildFullPatch(settings, new ChangeSet(toVersion), builder); + } else { + buildIncrementalPatch(settings, new ChangeSet(fromVersion), new ChangeSet(toVersion), builder); + } + } + + // builds patch from version to version + private void buildIncrementalPatch(final Settings settings, @NotNull final ChangeSet fromVer, @NotNull final ChangeSet toVer, final PatchBuilder builder) + throws VcsException, IOException { + StatusCommand st = new StatusCommand(settings); + st.setFromRevId(fromVer.getId()); + st.setToRevId(toVer.getId()); + List modifiedFiles = st.execute(); + List notDeletedFiles = new ArrayList(); + for (ModifiedFile f: modifiedFiles) { + if (f.getStatus() != ModifiedFile.Status.REMOVED) { + notDeletedFiles.add(f.getPath()); + } + } + + CatCommand cc = new CatCommand(settings); + cc.setRevId(toVer.getId()); + File parentDir = cc.execute(notDeletedFiles); + + try { + for (ModifiedFile f: modifiedFiles) { + final File virtualFile = new File(f.getPath()); + if (f.getStatus() == ModifiedFile.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(); + } + } + } + } finally { + FileUtil.delete(parentDir); + } + } + + // builds patch by exporting files using specified version + private void buildFullPatch(final Settings settings, @NotNull final ChangeSet toVer, final PatchBuilder builder) + throws IOException, VcsException { + CloneCommand cl = new CloneCommand(settings); + cl.setToId(toVer.getId()); + File tempDir = FileUtil.createTempDirectory("mercurial", toVer.getId()); + try { + final File repRoot = new File(tempDir, "rep"); + cl.setDestDir(repRoot.getAbsolutePath()); + cl.execute(); + buildPatchFromDirectory(builder, repRoot, new FileFilter() { + public boolean accept(final File file) { + return !(file.isDirectory() && ".hg".equals(file.getName())); + } + }); + } finally { + FileUtil.delete(tempDir); + } + } + + private void buildPatchFromDirectory(final PatchBuilder builder, final File repRoot, final FileFilter filter) throws IOException { + buildPatchFromDirectory(repRoot, builder, repRoot, filter); + } + + private void buildPatchFromDirectory(File curDir, final PatchBuilder builder, final File repRoot, final FileFilter filter) throws IOException { + File[] files = curDir.listFiles(filter); + if (files != null) { + for (File realFile: files) { + String relPath = realFile.getAbsolutePath().substring(repRoot.getAbsolutePath().length()); + final File virtualFile = new File(relPath); + if (realFile.isDirectory()) { + builder.createDirectory(virtualFile); + buildPatchFromDirectory(realFile, builder, repRoot, filter); + } else { + final FileInputStream is = new FileInputStream(realFile); + try { + builder.createBinaryFile(virtualFile, null, is, realFile.length()); + } finally { + is.close(); + } + } + } + } + } + + // updates current working copy of repository by pulling changes from the repository specified in VCS root + private void updateWorkingDirectory(final VcsRoot root) throws VcsException { + Settings settings = new Settings(myDefaultWorkFolderParent, root); + File workDir = settings.getWorkingDir(); + lockWorkDir(workDir); + try { + if (hasRepositoryCopy(workDir)) { + // update + PullCommand pull = new PullCommand(settings); + pull.execute(); + } else { + // clone + CloneCommand cl = new CloneCommand(settings); + cl.setDestDir(workDir.getAbsolutePath()); + cl.setUpdateWorkingDir(false); + cl.execute(); + } + } finally { + unlockWorkDir(workDir); + } + } + + private void lockWorkDir(@NotNull File workDir) { + getWorkDirLock(workDir).lock(); + } + + private void unlockWorkDir(@NotNull File workDir) { + getWorkDirLock(workDir).unlock(); + } + + private Lock getWorkDirLock(final File workDir) { + String path = workDir.getAbsolutePath(); + Lock lock = myWorkDirLocks.get(path); + if (lock == null) { + lock = new ReentrantLock(); + Lock curLock = myWorkDirLocks.putIfAbsent(path, lock); + if (curLock != null) { + lock = curLock; + } + } + return lock; + } + + private boolean hasRepositoryCopy(final File workDir) { + // need better way to check that repository copy is ok + return workDir.isDirectory() && new File(workDir, ".hg").isDirectory(); + } + + private void removeOldWorkFolders() { + File workFoldersParent = new File(myServerPaths.getCachesDir(), "mercurial"); + if (!workFoldersParent.isDirectory()) return; + + Set workDirs = new HashSet(); + File[] files = workFoldersParent.listFiles(new FileFilter() { + public boolean accept(final File file) { + return file.isDirectory() && file.getName().startsWith(Settings.DEFAULT_WORK_DIR_PREFIX); + } + }); + if (files != null) { + for (File f: files) { + workDirs.add(FileUtil.getCanonicalFile(f)); + } + } + + for (VcsRoot vcsRoot: myVcsManager.getAllRegisteredVcsRoots()) { + if (getName().equals(vcsRoot.getVcsName())) { + Settings s = new Settings(myDefaultWorkFolderParent, vcsRoot); + workDirs.remove(FileUtil.getCanonicalFile(s.getWorkingDir())); + } + } + + for (File f: workDirs) { + lockWorkDir(f); + try { + FileUtil.delete(f); + } finally { + unlockWorkDir(f); + } + } + } +} diff -r de75221eb196 -r 7944e8985ebd mercurial-tests/mercurial-tests.iml --- a/mercurial-tests/mercurial-tests.iml Mon Jul 21 21:22:25 2008 +0400 +++ b/mercurial-tests/mercurial-tests.iml Wed Jul 23 09:18:03 2008 +0400 @@ -8,11 +8,13 @@ - + + + diff -r de75221eb196 -r 7944e8985ebd mercurial.ipr --- a/mercurial.ipr Mon Jul 21 21:22:25 2008 +0400 +++ b/mercurial.ipr Wed Jul 23 09:18:03 2008 +0400 @@ -304,7 +304,9 @@ - + + + @@ -435,22 +437,21 @@

    - *
  • clones repository to internal storage - *
  • before any operation with working copy of repository pulls changes from the original repository - *
  • executes corresponding hg command - *
- * - *

Working copy of repository is created in the $TEAMCITY_DATA_PATH/system/caches/mercurial folder. - *

Personal builds (remote runs) are not yet supported, they require corresponding functionality from the IDE. - *

Checkout on agent mode is not yet supported too. - */ -public class MercurialVcsSupport extends VcsSupport implements CollectChangesByIncludeRule { - private ServerPaths myServerPaths; - private ConcurrentMap myWorkDirLocks= new ConcurrentHashMap(); - private static final int OLD_WORK_DIRS_CLEANUP_PERIOD = 600; - private VcsManager myVcsManager; - - public MercurialVcsSupport(@NotNull final VcsManager vcsManager, - @NotNull ServerPaths paths, - @NotNull SBuildServer server) { - vcsManager.registerVcsSupport(this); - myServerPaths = paths; - myVcsManager = vcsManager; - server.getExecutor().scheduleAtFixedRate(new Runnable() { - public void run() { - removeOldWorkFolders(); - } - }, 0, OLD_WORK_DIRS_CLEANUP_PERIOD, TimeUnit.SECONDS); - } - - public List collectBuildChanges(final VcsRoot root, - @NotNull final String fromVersion, - @NotNull final String currentVersion, - final CheckoutRules checkoutRules) throws VcsException { - updateWorkingDirectory(root); - return VcsSupportUtil.collectBuildChanges(root, fromVersion, currentVersion, checkoutRules, this); - } - - public List collectBuildChanges(final VcsRoot root, - final String fromVersion, - final String currentVersion, - final IncludeRule includeRule) throws VcsException { - // first obtain changes between specified versions - List result = new ArrayList(); - Settings settings = new Settings(myServerPaths, root); - LogCommand lc = new LogCommand(settings); - lc.setFromRevId(new ChangeSet(fromVersion).getId()); - lc.setToRevId(new ChangeSet(currentVersion).getId()); - List changeSets = lc.execute(); - if (changeSets.isEmpty()) { - return result; - } - - // invoke status command for each changeset and determine what files were modified in these changesets - Iterator it = changeSets.iterator(); - ChangeSet prev = it.next(); // skip first changeset (cause it was already reported) - StatusCommand st = new StatusCommand(settings); - while (it.hasNext()) { - ChangeSet cur = it.next(); - st.setFromRevId(prev.getId()); - st.setToRevId(cur.getId()); - List modifiedFiles = st.execute(); - // changeset full version will be set into VcsChange structure and - // stored in database (note that getContent method will be invoked with this version) - List files = toVcsChanges(modifiedFiles, prev.getFullVersion(), cur.getFullVersion(), includeRule); - if (files.isEmpty()) continue; - ModificationData md = new ModificationData(cur.getTimestamp(), files, cur.getSummary(), cur.getUser(), root, cur.getFullVersion(), cur.getFullVersion()); - result.add(md); - prev = cur; - } - - return result; - } - - private List toVcsChanges(final List modifiedFiles, String prevVer, String curVer, final IncludeRule includeRule) { - List files = new ArrayList(); - for (ModifiedFile mf: modifiedFiles) { - String normalizedPath = PathUtil.normalizeSeparator(mf.getPath()); - if (!normalizedPath.startsWith(includeRule.getFrom())) continue; // skip files which do not match include rule - - VcsChangeInfo.Type changeType = getChangeType(mf.getStatus()); - if (changeType == null) { - Loggers.VCS.warn("Unable to convert status: " + mf.getStatus() + " to VCS change type"); - changeType = VcsChangeInfo.Type.NOT_CHANGED; - } - files.add(new VcsChange(changeType, mf.getStatus().getName(), normalizedPath, normalizedPath, prevVer, curVer)); - } - return files; - } - - private VcsChangeInfo.Type getChangeType(final ModifiedFile.Status status) { - switch (status) { - case ADDED:return VcsChangeInfo.Type.ADDED; - case MODIFIED:return VcsChangeInfo.Type.CHANGED; - case REMOVED:return VcsChangeInfo.Type.REMOVED; - } - return null; - } - - @NotNull - public byte[] getContent(final VcsModification vcsModification, - final VcsChangeInfo change, - final VcsChangeInfo.ContentType contentType, - final VcsRoot vcsRoot) throws VcsException { - updateWorkingDirectory(vcsRoot); - String version = contentType == VcsChangeInfo.ContentType.AFTER_CHANGE ? change.getAfterChangeRevisionNumber() : change.getBeforeChangeRevisionNumber(); - return getContent(change.getRelativeFileName(), vcsRoot, version); - } - - @NotNull - public byte[] getContent(final String filePath, final VcsRoot vcsRoot, final String version) throws VcsException { - updateWorkingDirectory(vcsRoot); - Settings settings = new Settings(myServerPaths, vcsRoot); - CatCommand cc = new CatCommand(settings); - ChangeSet cs = new ChangeSet(version); - cc.setRevId(cs.getId()); - File parentDir = cc.execute(Collections.singletonList(filePath)); - File file = new File(parentDir, filePath); - if (file.isFile()) { - try { - return FileUtil.loadFileBytes(file); - } catch (IOException e) { - throw new VcsException("Failed to load content of file: " + file.getAbsolutePath(), e); - } - } else { - Loggers.VCS.warn("Unable to obtain content of the file: " + filePath); - } - return new byte[0]; - } - - public String getName() { - return "mercurial"; - } - - @Used("jsp") - public String getDisplayName() { - return "Mercurial"; - } - - @Nullable - public PropertiesProcessor getVcsPropertiesProcessor() { - return new AbstractVcsPropertiesProcessor() { - public Collection process(final Map properties) { - List result = new ArrayList(); - if (isEmpty(properties.get(Constants.HG_COMMAND_PATH_PROP))) { - result.add(new InvalidProperty(Constants.HG_COMMAND_PATH_PROP, "Path to 'hg' command must be specified")); - } - if (isEmpty(properties.get(Constants.REPOSITORY_PROP))) { - result.add(new InvalidProperty(Constants.REPOSITORY_PROP, "Repository must be specified")); - } - return result; - } - }; - } - - public String getVcsSettingsJspFilePath() { - return "mercurialSettings.jsp"; - } - - @NotNull - public String getCurrentVersion(final VcsRoot root) throws VcsException { - // we will return full version of the most recent change as current version - updateWorkingDirectory(root); - Settings settings = new Settings(myServerPaths, root); - TipCommand lc = new TipCommand(settings); - ChangeSet changeSet = lc.execute(); - return changeSet.getFullVersion(); - } - - public String describeVcsRoot(final VcsRoot vcsRoot) { - return "mercurial: " + vcsRoot.getProperty(Constants.REPOSITORY_PROP); - } - - public boolean isTestConnectionSupported() { - return true; - } - - @Nullable - public String testConnection(final VcsRoot vcsRoot) throws VcsException { - Settings settings = new Settings(myServerPaths, vcsRoot); - IdentifyCommand id = new IdentifyCommand(settings); - StringBuilder res = new StringBuilder(); - res.append(quoteIfNeeded(settings.getHgCommandPath())); - res.append(" identify "); - res.append(quoteIfNeeded(settings.getRepository())); - res.append('\n').append(id.execute()); - return res.toString(); - } - - private String quoteIfNeeded(@NotNull String str) { - if (str.indexOf(' ') != -1) { - return "\"" + str + "\""; - } - - return str; - } - - @Nullable - public Map getDefaultVcsProperties() { - return Collections.singletonMap(Constants.HG_COMMAND_PATH_PROP, "hg"); - } - - public String getVersionDisplayName(final String version, final VcsRoot root) throws VcsException { - return version; - } - - @NotNull - public Comparator getVersionComparator() { - // comparator is called when TeamCity needs to sort modifications in the order of their appearance, - // currently we sort changes by revision number, not sure however that this is a good idea, - // probably it would be better to sort them by timestamp (and to add timestamp into the version). - return new Comparator() { - public int compare(final String o1, final String o2) { - try { - return new ChangeSet(o1).getRevNumber() - new ChangeSet(o2).getRevNumber(); - } catch (Exception e) { - return 1; - } - } - }; - } - - public void buildPatch(final VcsRoot root, - @Nullable final String fromVersion, - @NotNull final String toVersion, - final PatchBuilder builder, - final CheckoutRules checkoutRules) throws IOException, VcsException { - updateWorkingDirectory(root); - Settings settings = new Settings(myServerPaths, root); - if (fromVersion == null) { - buildFullPatch(settings, new ChangeSet(toVersion), builder); - } else { - buildIncrementalPatch(settings, new ChangeSet(fromVersion), new ChangeSet(toVersion), builder); - } - } - - // builds patch from version to version - private void buildIncrementalPatch(final Settings settings, @NotNull final ChangeSet fromVer, @NotNull final ChangeSet toVer, final PatchBuilder builder) - throws VcsException, IOException { - StatusCommand st = new StatusCommand(settings); - st.setFromRevId(fromVer.getId()); - st.setToRevId(toVer.getId()); - List modifiedFiles = st.execute(); - List notDeletedFiles = new ArrayList(); - for (ModifiedFile f: modifiedFiles) { - if (f.getStatus() != ModifiedFile.Status.REMOVED) { - notDeletedFiles.add(f.getPath()); - } - } - - CatCommand cc = new CatCommand(settings); - cc.setRevId(toVer.getId()); - File parentDir = cc.execute(notDeletedFiles); - - try { - for (ModifiedFile f: modifiedFiles) { - final File virtualFile = new File(f.getPath()); - if (f.getStatus() == ModifiedFile.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(); - } - } - } - } finally { - FileUtil.delete(parentDir); - } - } - - // builds patch by exporting files using specified version - private void buildFullPatch(final Settings settings, @NotNull final ChangeSet toVer, final PatchBuilder builder) - throws IOException, VcsException { - CloneCommand cl = new CloneCommand(settings); - cl.setToId(toVer.getId()); - File tempDir = FileUtil.createTempDirectory("mercurial", toVer.getId()); - try { - final File repRoot = new File(tempDir, "rep"); - cl.setDestDir(repRoot.getAbsolutePath()); - cl.execute(); - buildPatchFromDirectory(builder, repRoot, new FileFilter() { - public boolean accept(final File file) { - return !(file.isDirectory() && ".hg".equals(file.getName())); - } - }); - } finally { - FileUtil.delete(tempDir); - } - } - - private void buildPatchFromDirectory(final PatchBuilder builder, final File repRoot, final FileFilter filter) throws IOException { - buildPatchFromDirectory(repRoot, builder, repRoot, filter); - } - - private void buildPatchFromDirectory(File curDir, final PatchBuilder builder, final File repRoot, final FileFilter filter) throws IOException { - File[] files = curDir.listFiles(filter); - if (files != null) { - for (File realFile: files) { - String relPath = realFile.getAbsolutePath().substring(repRoot.getAbsolutePath().length()); - final File virtualFile = new File(relPath); - if (realFile.isDirectory()) { - builder.createDirectory(virtualFile); - buildPatchFromDirectory(realFile, builder, repRoot, filter); - } else { - final FileInputStream is = new FileInputStream(realFile); - try { - builder.createBinaryFile(virtualFile, null, is, realFile.length()); - } finally { - is.close(); - } - } - } - } - } - - // updates current working copy of repository by pulling changes from the repository specified in VCS root - private void updateWorkingDirectory(final VcsRoot root) throws VcsException { - Settings settings = new Settings(myServerPaths, root); - File workDir = settings.getWorkingDir(); - lockWorkDir(workDir); - try { - if (hasRepositoryCopy(workDir)) { - // update - PullCommand pull = new PullCommand(settings); - pull.execute(); - } else { - // clone - CloneCommand cl = new CloneCommand(settings); - cl.setDestDir(workDir.getAbsolutePath()); - cl.setUpdateWorkingDir(false); - cl.execute(); - } - } finally { - unlockWorkDir(workDir); - } - } - - private void lockWorkDir(@NotNull File workDir) { - getWorkDirLock(workDir).lock(); - } - - private void unlockWorkDir(@NotNull File workDir) { - getWorkDirLock(workDir).unlock(); - } - - private Lock getWorkDirLock(final File workDir) { - String path = workDir.getAbsolutePath(); - Lock lock = myWorkDirLocks.get(path); - if (lock == null) { - lock = new ReentrantLock(); - Lock curLock = myWorkDirLocks.putIfAbsent(path, lock); - if (curLock != null) { - lock = curLock; - } - } - return lock; - } - - private boolean hasRepositoryCopy(final File workDir) { - // need better way to check that repository copy is ok - return workDir.isDirectory() && new File(workDir, ".hg").isDirectory(); - } - - private void removeOldWorkFolders() { - File workFoldersParent = new File(myServerPaths.getCachesDir(), "mercurial"); - if (!workFoldersParent.isDirectory()) return; - - Set workDirs = new HashSet(); - File[] files = workFoldersParent.listFiles(new FileFilter() { - public boolean accept(final File file) { - return file.isDirectory() && file.getName().startsWith(Settings.DEFAULT_WORK_DIR_PREFIX); - } - }); - if (files != null) { - for (File f: files) { - workDirs.add(FileUtil.getCanonicalFile(f)); - } - } - - for (VcsRoot vcsRoot: myVcsManager.getAllRegisteredVcsRoots()) { - if (getName().equals(vcsRoot.getVcsName())) { - Settings s = new Settings(myServerPaths, vcsRoot); - workDirs.remove(FileUtil.getCanonicalFile(s.getWorkingDir())); - } - } - - for (File f: workDirs) { - lockWorkDir(f); - try { - FileUtil.delete(f); - } finally { - unlockWorkDir(f); - } - } - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/PathUtil.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/PathUtil.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2007 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 org.jetbrains.annotations.NotNull; - -public class PathUtil { - @NotNull - public static String normalizeSeparator(@NotNull String repPath) { - return repPath.replace('\\', '/'); - } - } diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CatCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CatCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.util.FileUtil; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -public class CatCommand { - private Settings mySettings; - private String myRevId; - - public CatCommand(@NotNull final Settings settings) { - mySettings = settings; - } - - public void setRevId(final String revId) { - myRevId = revId; - } - - public File execute(List relPaths) throws VcsException { - File tempDir; - try { - tempDir = FileUtil.createTempDirectory("mercurial", "catresult"); - } catch (IOException e) { - throw new VcsException("Unable to create temporary directory"); - } - for (String path: relPaths) { - final File parentFile = new File(tempDir, path).getParentFile(); - if (!parentFile.isDirectory() && !parentFile.mkdirs()) { - throw new VcsException("Failed to create directory: " + parentFile.getAbsolutePath()); - } - } - - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setExePath(mySettings.getHgCommandPath()); - cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); - cli.addParameter("cat"); - cli.addParameter("-o"); - cli.addParameter(tempDir.getAbsolutePath() + File.separator + "%p"); - if (myRevId != null) { - cli.addParameter("-r"); - cli.addParameter(myRevId); - } - for (String p: relPaths) { - cli.addParameter(FileUtil.normalizeSeparator(p)); - } - CommandUtil.runCommand(cli); - return tempDir; - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * Copyright 2000-2007 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; - -import java.util.Date; - -/** - * Represents Mercurial change set - */ -public class ChangeSet { - private int myRevNumber; - @NotNull private String myId; - @NotNull private String myUser; - @NotNull private Date myTimestamp; - private String mySummary; - - public ChangeSet(final int revNumber, @NotNull final String id) { - myRevNumber = revNumber; - myId = id; - } - - /** - * Constructor for version in the form revnum:changeset_id - * @param fullVersion full changeset version as reported by hg log command - */ - public ChangeSet(@NotNull final String fullVersion) { - try { - String[] parts = fullVersion.split(":"); - myRevNumber = Integer.parseInt(parts[0]); - myId = parts[1]; - } catch (Throwable e) { - throw new IllegalArgumentException(e); - } - } - - public void setUser(@NotNull final String user) { - myUser = user; - } - - public void setTimestamp(@NotNull final Date timestamp) { - myTimestamp = timestamp; - } - - public void setSummary(final String summary) { - mySummary = summary; - } - - /** - * Returns changeset revision id - * @return changeset revision id - */ - @NotNull - public String getId() { - return myId; - } - - /** - * Returns changeset revision number - * @return changeset revision number - */ - public int getRevNumber() { - return myRevNumber; - } - - /** - * Returns full changeset version as reported by hg log command: revnum:revid - * @return full changeset version as reported by hg log - */ - @NotNull - public String getFullVersion() { - return myRevNumber + ":" + myId; - } - - /** - * Returns user who made changeset - * @return user who made changeset - */ - @NotNull - public String getUser() { - return myUser; - } - - /** - * Returns changeset timestamp - * @return changeset timestamp - */ - @NotNull - public Date getTimestamp() { - return myTimestamp; - } - - /** - * Returns changeset summary specified by user - * @return changeset summary - */ - public String getSummary() { - return mySummary; - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CloneCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CloneCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -import java.io.File; - -public class CloneCommand { - private Settings mySettings; - private String myDestDir; - private String myToId; - private boolean myUpdateWorkingDir = true; - - public CloneCommand(@NotNull final Settings settings) { - mySettings = settings; - } - - public void setDestDir(@NotNull String destDir) { - myDestDir = destDir; - } - - public void setToId(final String toId) { - myToId = toId; - } - - public void setUpdateWorkingDir(final boolean updateWorkingDir) { - myUpdateWorkingDir = updateWorkingDir; - } - - public void execute() throws VcsException { - if (myDestDir == null) throw new IllegalStateException("Destination dir must be specified"); - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setExePath(mySettings.getHgCommandPath()); - File dir = new File(myDestDir); - File parent = dir.getParentFile(); - cli.setWorkDirectory(parent.getAbsolutePath()); - cli.addParameter("clone"); - if (myToId != null) { - cli.addParameter("-r"); - cli.addParameter(myToId); - } - cli.addParameter("--pull"); - if (!myUpdateWorkingDir) { - cli.addParameter("-U"); - } - cli.addParameter(mySettings.getRepository()); - cli.addParameter(dir.getName()); - - CommandUtil.runCommand(cli); - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.ExecResult; -import jetbrains.buildServer.SimpleCommandLineProcessRunner; -import jetbrains.buildServer.log.Loggers; -import jetbrains.buildServer.util.StringUtil; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -public class CommandUtil { - public static void checkCommandFailed(@NotNull String cmdName, @NotNull ExecResult res) throws VcsException { - if (res.getExitCode() > 0 || res.getException() != null) { - commandFailed(cmdName, res); - } - } - - public static void commandFailed(final String cmdName, final ExecResult res) throws VcsException { - Throwable exception = res.getException(); - String stderr = res.getStderr(); - String stdout = res.getStdout(); - final String message = "'" + cmdName + "' command failed.\n" + - (!StringUtil.isEmpty(stderr) ? "stderr: " + stderr + "\n" : "") + - (!StringUtil.isEmpty(stdout) ? "stdout: " + stdout + "\n" : "") + - (exception != null ? "exception: " + exception.getLocalizedMessage() : ""); - Loggers.VCS.warn(message); - throw new VcsException(message); - } - - public static ExecResult runCommand(@NotNull GeneralCommandLine cli) throws VcsException { - String cmdStr = cli.getCommandLineString(); - Loggers.VCS.debug("Run command: " + cmdStr); - ExecResult res = SimpleCommandLineProcessRunner.runCommand(cli, null); - CommandUtil.checkCommandFailed(cmdStr, res); - return res; - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/IdentifyCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/IdentifyCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.ExecResult; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -/** - * @author Pavel.Sher - * Date: 16.07.2008 - */ -public class IdentifyCommand { - private Settings mySettings; - - public IdentifyCommand(@NotNull final Settings settings) { - mySettings = settings; - } - - public String execute() throws VcsException { - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setExePath(mySettings.getHgCommandPath()); - cli.addParameter("identify"); - cli.addParameter(mySettings.getRepository()); - ExecResult res = CommandUtil.runCommand(cli); - if (res.getStderr().length() > 0) { - CommandUtil.commandFailed(cli.getCommandLineString(), res); - } - return res.getStdout(); - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.openapi.diagnostic.Logger; -import jetbrains.buildServer.ExecResult; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -public class LogCommand { - private final static Logger LOG = Logger.getInstance(LogCommand.class.getName()); - private String myFromId; - private String myToId; - private Settings mySettings; - private static final String CHANGESET_PREFIX = "changeset:"; - private static final String USER_PREFIX = "user:"; - private static final String DATE_PREFIX = "date:"; - private static final String DATE_FORMAT = "EEE MMM d HH:mm:ss yyyy Z"; - private static final String SUMMARY_PREFIX = "summary:"; - - public LogCommand(@NotNull Settings settings) { - mySettings = settings; - } - - public void setFromRevId(String id) { - myFromId = id; - } - - public void setToRevId(String id) { - myToId = id; - } - - public List execute() throws VcsException { - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setExePath(mySettings.getHgCommandPath()); - cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); - cli.addParameter("log"); - cli.addParameter("-r"); - String from = myFromId; - if (from == null) from = "0"; - String to = myToId; - if (to == null) to = "0"; - cli.addParameter(from + ":" + to); - - ExecResult res = CommandUtil.runCommand(cli); - return parseChangeSets(res.getStdout()); - } - - public static List parseChangeSets(final String stdout) { - List result = new ArrayList(); - String[] lines = stdout.split("\n"); - ChangeSet current = null; - int lineNum = 0; - while (lineNum < lines.length) { - String line = lines[lineNum]; - lineNum++; - - if (line.startsWith(CHANGESET_PREFIX)) { - String revAndId = line.substring(CHANGESET_PREFIX.length()).trim(); - try { - current = new ChangeSet(revAndId); - result.add(current); - } catch (IllegalArgumentException e) { - LOG.warn("Unable to extract changeset id from the line: " + line); - } - - continue; - } - - if (current == null) continue; - - if (line.startsWith(USER_PREFIX)) { - current.setUser(line.substring(USER_PREFIX.length()).trim()); - continue; - } - - if (line.startsWith(DATE_PREFIX)) { - String date = line.substring(DATE_PREFIX.length()).trim(); - try { - Date parsedDate = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH).parse(date); - current.setTimestamp(parsedDate); - } catch (ParseException e) { - LOG.warn("Unable to parse date: " + date); - current = null; - } - - continue; - } - - if (line.startsWith(SUMMARY_PREFIX)) { - String summary = line.substring(SUMMARY_PREFIX.length()).trim(); - current.setSummary(summary); - - continue; - } - } - - return result; - } - -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright 2000-2007 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; - -/** - * Represents repository modified file - */ -public class ModifiedFile { - /** - * Type of modification - */ - public static enum Status { - ADDED("added"), - MODIFIED("modified"), - REMOVED("removed"), - UNKNOWN("unknown"); - private String myName; - - Status(@NotNull final String name) { - myName = name; - } - - @NotNull - public String getName() { - return myName; - } - } - - @NotNull private Status myStatus; - @NotNull private String myPath; - - public ModifiedFile(@NotNull final Status status, @NotNull final String path) { - myStatus = status; - myPath = path; - } - - /** - * Returns type of modification - * @return type of modification - */ - @NotNull - public Status getStatus() { - return myStatus; - } - - /** - * Returns file path - * @return file path - */ - @NotNull - public String getPath() { - return myPath; - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -/** - * @author Pavel.Sher - * Date: 14.07.2008 - */ -public class PullCommand { - private Settings mySettings; - - public PullCommand(@NotNull final Settings settings) { - mySettings = settings; - } - - public void execute() throws VcsException { - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setExePath(mySettings.getHgCommandPath()); - cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); - cli.addParameter("pull"); - cli.addParameter(mySettings.getRepository()); - CommandUtil.runCommand(cli); - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/Settings.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/Settings.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * Copyright 2000-2007 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.buildTriggers.vcs.mercurial.PathUtil; -import jetbrains.buildServer.serverSide.ServerPaths; -import jetbrains.buildServer.vcs.VcsRoot; -import jetbrains.buildServer.util.Hash; -import jetbrains.buildServer.util.FileUtil; -import org.jetbrains.annotations.NotNull; - -import java.io.File; - -/** - * Represents Mercurial repository settings - */ -public class Settings { - private String myRepository; - private String myHgCommandPath; - private ServerPaths myServerPaths; - private File myWorkingDir; - - public Settings(@NotNull ServerPaths paths, @NotNull VcsRoot vcsRoot) { - myServerPaths = paths; - setRepository(vcsRoot.getProperty(Constants.REPOSITORY_PROP)); - setHgCommandPath(vcsRoot.getProperty(Constants.HG_COMMAND_PATH_PROP)); - } - - public Settings() { - } - - public void setRepository(@NotNull final String repository) { - myRepository = repository; - } - - /** - * Returns repository path - * @return repository path - */ - @NotNull - public String getRepository() { - return myRepository; - } - - /** - * Returns path to hg command - * @return path to hg command - */ - @NotNull - public String getHgCommandPath() { - return myHgCommandPath; - } - - public void setHgCommandPath(@NotNull final String hgCommandPath) { - myHgCommandPath = hgCommandPath; - } - - public void setWorkingDir(@NotNull final File workingDir) { - myWorkingDir = FileUtil.getCanonicalFile(workingDir); - } - - /** - * Returns repository working directory where all mercurial commands should be invoked - * @return repository working directory - */ - @NotNull - public File getWorkingDir() { - if (myWorkingDir != null) { - return myWorkingDir; - } - - return getDefaultWorkDir(myServerPaths, myRepository); - } - - public static String DEFAULT_WORK_DIR_PREFIX = "hg_"; - - private static File getDefaultWorkDir(@NotNull ServerPaths serverPaths, @NotNull String repPath) { - String workingDirname = DEFAULT_WORK_DIR_PREFIX + String.valueOf(Hash.calc(normalize(repPath))); - File workFoldersRootDir = new File(serverPaths.getCachesDir(), "mercurial"); - if (!workFoldersRootDir.mkdirs() && !workFoldersRootDir.isDirectory()) { - throw new RuntimeException("Cannot create directory: " + workFoldersRootDir.getAbsolutePath()); - } - return FileUtil.getCanonicalFile(new File(workFoldersRootDir, workingDirname)); - } - - private static String normalize(final String path) { - String normalized = PathUtil.normalizeSeparator(path); - if (path.endsWith("/")) { - return normalized.substring(0, normalized.length()-1); - } - return normalized; - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/StatusCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/StatusCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.ExecResult; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -public class StatusCommand { - private Settings mySettings; - private String myFromId; - private String myToId; - - public StatusCommand(@NotNull final Settings settings) { - mySettings = settings; - } - - public void setFromRevId(final String fromId) { - myFromId = fromId; - } - - public void setToRevId(final String toId) { - myToId = toId; - } - - public List execute() throws VcsException { - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setExePath(mySettings.getHgCommandPath()); - cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); - cli.addParameter("status"); - cli.addParameter("--rev"); - String from = myFromId; - if (from == null) from = "0"; - String to = myToId; - if (to == null) to = "0"; - cli.addParameter(from + ":" + to); - ExecResult res = CommandUtil.runCommand(cli); - return parseFiles(res.getStdout()); - } - - private List parseFiles(final String stdout) { - List result = new ArrayList(); - String[] lines = stdout.split("\n"); - for (String line: lines) { - if (line.length() == 0) continue; - char modifier = line.charAt(0); - String path = line.substring(2); - ModifiedFile.Status status = toStatus(modifier); - if (status == ModifiedFile.Status.UNKNOWN) continue; - result.add(new ModifiedFile(status, path)); - } - return result; - } - - private ModifiedFile.Status toStatus(final char modifier) { - switch (modifier) { - case 'A': return ModifiedFile.Status.ADDED; - case 'M': return ModifiedFile.Status.MODIFIED; - case 'R': return ModifiedFile.Status.REMOVED; - default: return ModifiedFile.Status.UNKNOWN; - } - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/TipCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/TipCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.ExecResult; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * @author Pavel.Sher - * Date: 14.07.2008 - */ -public class TipCommand { - @NotNull - private Settings mySettings; - - public TipCommand(@NotNull final Settings settings) { - mySettings = settings; - } - - @NotNull - public ChangeSet execute() throws VcsException { - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); - cli.setExePath(mySettings.getHgCommandPath()); - cli.addParameter("tip"); - ExecResult res = CommandUtil.runCommand(cli); - List changeSets = LogCommand.parseChangeSets(res.getStdout()); - if (changeSets.isEmpty()) { - CommandUtil.commandFailed("hg tip", res); - } - - return changeSets.get(0); - } -} diff -r de75221eb196 -r 7944e8985ebd mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/UpdateCommand.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/UpdateCommand.java Mon Jul 21 21:22:25 2008 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright 2000-2007 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 com.intellij.execution.configurations.GeneralCommandLine; -import jetbrains.buildServer.vcs.VcsException; -import org.jetbrains.annotations.NotNull; - -public class UpdateCommand { - private Settings mySettings; - - public UpdateCommand(@NotNull final Settings settings) { - mySettings = settings; - } - - public void execute() throws VcsException { - GeneralCommandLine cli = new GeneralCommandLine(); - cli.setExePath(mySettings.getHgCommandPath()); - cli.setWorkDirectory(mySettings.getWorkingDir().getAbsolutePath()); - cli.addParameter("update"); - cli.addParameter("-C"); - CommandUtil.runCommand(cli); - } -}