# HG changeset patch # User Pavel.Sher # Date 1216215461 -14400 # Node ID 40b2cf04cd4bf4a583b4abea632066e21681a67c # Parent d787c696225c92fb5feb2a011ca6a930259c619a some comments added diff -r d787c696225c -r 40b2cf04cd4b mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Wed Jul 16 01:48:22 2008 +0400 +++ b/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Wed Jul 16 17:37:41 2008 +0400 @@ -20,6 +20,18 @@ import java.io.IOException; import java.util.*; +/** + * Mercurial VCS plugin for TeamCity works as follows: + * + * + *

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; @@ -40,6 +52,7 @@ 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); @@ -50,6 +63,7 @@ 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); @@ -58,6 +72,8 @@ 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 than 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()); @@ -159,6 +175,7 @@ @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); @@ -196,7 +213,7 @@ @Nullable public Map getDefaultVcsProperties() { - return null; + return Collections.singletonMap(Constants.HG_COMMAND_PATH_PROP, "hg"); } public String getVersionDisplayName(final String version, final VcsRoot root) throws VcsException { @@ -205,6 +222,9 @@ @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 { @@ -230,6 +250,7 @@ } } + // 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); @@ -267,6 +288,7 @@ } } + // 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); @@ -311,6 +333,7 @@ } } + // 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); String workDir = settings.getWorkingDir(); @@ -330,6 +353,7 @@ } private boolean hasRepositoryCopy(final File workDir) { + // need better way to check that repository copy is ok return workDir.isDirectory() && new File(workDir, ".hg").isDirectory(); } diff -r d787c696225c -r 40b2cf04cd4b mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java Wed Jul 16 01:48:22 2008 +0400 +++ b/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java Wed Jul 16 17:37:41 2008 +0400 @@ -4,6 +4,9 @@ import java.util.Date; +/** + * Represents Mercurial change set + */ public class ChangeSet { private int myRevNumber; @NotNull private String myId; @@ -16,6 +19,10 @@ 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(":"); @@ -38,30 +45,54 @@ 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 d787c696225c -r 40b2cf04cd4b mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java Wed Jul 16 01:48:22 2008 +0400 +++ b/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java Wed Jul 16 17:37:41 2008 +0400 @@ -2,7 +2,13 @@ import org.jetbrains.annotations.NotNull; +/** + * Represents repository modified file + */ public class ModifiedFile { + /** + * Type of modification + */ public static enum Status { ADDED("added"), MODIFIED("modified"), @@ -28,11 +34,19 @@ 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 d787c696225c -r 40b2cf04cd4b mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/Settings.java --- a/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/Settings.java Wed Jul 16 01:48:22 2008 +0400 +++ b/mercurial/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/Settings.java Wed Jul 16 17:37:41 2008 +0400 @@ -7,6 +7,9 @@ import java.io.File; +/** + * Represents Mercurial repository settings + */ public class Settings { private String myRepository; private String myHgCommandPath; @@ -26,11 +29,19 @@ 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; @@ -44,6 +55,10 @@ myWorkingDir = workingDir; } + /** + * Returns repository working directory where all mercurial commands should be invoked + * @return repository working directory + */ @NotNull public String getWorkingDir() { if (myWorkingDir != null) {