changeset 570:57b85306c377

Merge branch Faradi-7.1.x
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Mon, 18 Mar 2013 12:08:16 +0400
parents 333a1ddcbf94 (diff) 7ca3303cfc9e (current diff)
children c3ec73ac68ca
files mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentMirrorCleanerTest.java
diffstat 192 files changed, 2871 insertions(+), 1651 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Mar 18 12:05:23 2013 +0400
+++ b/.hgignore	Mon Mar 18 12:08:16 2013 +0400
@@ -2,4 +2,7 @@
 test-output
 .iws
 dist
-mercurial.properties
\ No newline at end of file
+mercurial.properties
+syntax: glob
+.idea/workspace.xml
+out
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/ant.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AntConfiguration">
+    <defaultAnt bundledAnt="true" />
+    <buildFile url="file://$PROJECT_DIR$/build.xml">
+      <additionalClassPath />
+      <antReference projectDefault="true" />
+      <customJdkName value="" />
+      <maximumHeapSize value="128" />
+      <maximumStackSize value="32" />
+      <properties />
+    </buildFile>
+    <buildFile url="file://$PROJECT_DIR$/build/ant.build.xml">
+      <additionalClassPath />
+      <antReference projectDefault="true" />
+      <customJdkName value="" />
+      <maximumHeapSize value="128" />
+      <maximumStackSize value="2" />
+      <properties />
+    </buildFile>
+  </component>
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/artifacts/mercurial_agent_jar.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,14 @@
+<component name="ArtifactManager">
+  <artifact type="jar" name="mercurial-agent.jar">
+    <output-path>$PROJECT_DIR$/out/artifacts/mercurial_agent_jar</output-path>
+    <properties id="ant-postprocessing">
+      <options enabled="true">
+        <file>file://$PROJECT_DIR$/build/ant.build.xml</file>
+        <target>replace-tokens-in-teamcity-plugin-xml</target>
+      </options>
+    </properties>
+    <root id="archive" name="mercurial-agent.jar">
+      <element id="module-output" name="mercurial-agent" />
+    </root>
+  </artifact>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/artifacts/mercurial_common_jar.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,8 @@
+<component name="ArtifactManager">
+  <artifact type="jar" name="mercurial-common.jar">
+    <output-path>$PROJECT_DIR$/out/artifacts/mercurial_common_jar</output-path>
+    <root id="archive" name="mercurial-common.jar">
+      <element id="module-output" name="mercurial-common" />
+    </root>
+  </artifact>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/artifacts/mercurial_server_jar.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,8 @@
+<component name="ArtifactManager">
+  <artifact type="jar" name="mercurial-server.jar">
+    <output-path>$PROJECT_DIR$/out/artifacts/mercurial_server_jar</output-path>
+    <root id="archive" name="mercurial-server.jar">
+      <element id="module-output" name="mercurial-server" />
+    </root>
+  </artifact>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/artifacts/mercurial_server_tc_jar.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,8 @@
+<component name="ArtifactManager">
+  <artifact type="jar" name="mercurial-server-tc.jar">
+    <output-path>$PROJECT_DIR$/out/artifacts/mercurial_server_tc_jar</output-path>
+    <root id="archive" name="mercurial-server-tc.jar">
+      <element id="module-output" name="mercurial-server-tc" />
+    </root>
+  </artifact>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/artifacts/plugin.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,29 @@
+<component name="ArtifactManager">
+  <artifact name="plugin">
+    <output-path>$PROJECT_DIR$/out/artifacts/plugin</output-path>
+    <properties id="ant-postprocessing">
+      <options enabled="true">
+        <file>file://$PROJECT_DIR$/build/ant.build.xml</file>
+        <target>replace-tokens-in-teamcity-plugin-xml</target>
+      </options>
+    </properties>
+    <root id="root">
+      <element id="directory" name="server">
+        <element id="artifact" artifact-name="mercurial-server.jar" />
+        <element id="artifact" artifact-name="mercurial-common.jar" />
+        <element id="artifact" artifact-name="mercurial-server-tc.jar" />
+      </element>
+      <element id="directory" name="agent">
+        <element id="archive" name="mercurial.zip">
+          <element id="directory" name="mercurial">
+            <element id="directory" name="lib">
+              <element id="artifact" artifact-name="mercurial-common.jar" />
+              <element id="artifact" artifact-name="mercurial-agent.jar" />
+            </element>
+          </element>
+        </element>
+      </element>
+      <element id="file-copy" path="$PROJECT_DIR$/teamcity-plugin.xml" />
+    </root>
+  </artifact>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/artifacts/zip.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,10 @@
+<component name="ArtifactManager">
+  <artifact name="zip">
+    <output-path>$PROJECT_DIR$/dist</output-path>
+    <root id="root">
+      <element id="archive" name="mercurial.zip">
+        <element id="artifact" artifact-name="plugin" />
+      </element>
+    </root>
+  </artifact>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/compiler.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <option name="DEFAULT_COMPILER" value="Javac" />
+    <resourceExtensions>
+      <entry name=".+\.(properties|xml|html|dtd|tld)" />
+      <entry name=".+\.(gif|png|jpeg|jpg)" />
+    </resourceExtensions>
+    <wildcardResourcePatterns>
+      <entry name="?*.properties" />
+      <entry name="?*.xml" />
+      <entry name="?*.gif" />
+      <entry name="?*.png" />
+      <entry name="?*.jpeg" />
+      <entry name="?*.jpg" />
+      <entry name="?*.html" />
+      <entry name="?*.dtd" />
+      <entry name="?*.tld" />
+      <entry name="?*.jsp" />
+      <entry name="?*.tag" />
+      <entry name="?*.template" />
+      <entry name="do-not-load-in-vcs-mode" />
+    </wildcardResourcePatterns>
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="false">
+        <processorPath useClasspath="true" />
+      </profile>
+    </annotationProcessing>
+  </component>
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/copyright/profiles_settings.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,5 @@
+<component name="CopyrightManager">
+  <settings default="">
+    <module2copyright />
+  </settings>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/encodings.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/inspectionProfiles/Project_Default.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,11 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0" is_locked="false">
+    <option name="myName" value="Project Default" />
+    <option name="myLocal" value="false" />
+    <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
+      <option name="processCode" value="true" />
+      <option name="processLiterals" value="true" />
+      <option name="processComments" value="true" />
+    </inspection_tool>
+  </profile>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/inspectionProfiles/profiles_settings.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,15 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="PROJECT_PROFILE" value="Project Default" />
+    <option name="USE_PROJECT_PROFILE" value="true" />
+    <version value="1.0" />
+    <list size="6">
+      <item index="0" class="java.lang.String" itemvalue="TYPO" />
+      <item index="1" class="java.lang.String" itemvalue="WEAK WARNING" />
+      <item index="2" class="java.lang.String" itemvalue="INFO" />
+      <item index="3" class="java.lang.String" itemvalue="WARNING" />
+      <item index="4" class="java.lang.String" itemvalue="ERROR" />
+      <item index="5" class="java.lang.String" itemvalue="SERVER PROBLEM" />
+    </list>
+  </settings>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/IDEA_openapi.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="IDEA-openapi">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/resources_en.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/util.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/openapi.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/annotations.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/JMock.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,15 @@
+<component name="libraryTable">
+  <library name="JMock">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-library-1.1.jar!/" />
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-core-1.1.jar!/" />
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/jmock-2.5.1.jar!/" />
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/jmock-SNAPSHOT.jar!/" />
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-integration-1.1.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-integration-1.1.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/JUnit.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="JUnit">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/junit-3.8.1.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/Log4j.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="Log4j">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-1.2.12.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/TeamCityAPI_agent.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="TeamCityAPI-agent">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/devPackage/agent-api.jar!/" />
+      <root url="jar://$TeamCityDistribution$/buildAgent/lib/agent.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/TeamCityAPI_common.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="TeamCityAPI-common">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/devPackage/common-api.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/TeamCityAPI_server.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="TeamCityAPI-server">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/devPackage/server-api.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/TeamCity_TestsAPI.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,10 @@
+<component name="libraryTable">
+  <library name="TeamCity-TestsAPI">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/devPackage/tests/patches-test.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/tests/tests-support.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/TeamCity_Vcs_Api.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="TeamCity Vcs Api">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/devPackage/server-common-api.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/server-vcs-api.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/TeamCity_impl.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,10 @@
+<component name="libraryTable">
+  <library name="TeamCity-impl">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/patches-impl.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove4j.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/TestNG.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="TestNG">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/testng-6.8.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/jdom.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="jdom">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/jdom.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/misc.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="EntryPointsManager">
+    <entry_points version="2.0" />
+  </component>
+  <component name="IdProvider" IDEtalkID="C52C76224CD45BEC1DC62428B699D800" />
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK" />
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/modules.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/main.iml" filepath="$PROJECT_DIR$/main.iml" />
+      <module fileurl="file://$PROJECT_DIR$/mercurial-agent/mercurial-agent.iml" filepath="$PROJECT_DIR$/mercurial-agent/mercurial-agent.iml" />
+      <module fileurl="file://$PROJECT_DIR$/mercurial-common/mercurial-common.iml" filepath="$PROJECT_DIR$/mercurial-common/mercurial-common.iml" />
+      <module fileurl="file://$PROJECT_DIR$/mercurial-server/mercurial-server.iml" filepath="$PROJECT_DIR$/mercurial-server/mercurial-server.iml" />
+      <module fileurl="file://$PROJECT_DIR$/mercurial-server-tc/mercurial-server-tc.iml" filepath="$PROJECT_DIR$/mercurial-server-tc/mercurial-server-tc.iml" />
+      <module fileurl="file://$PROJECT_DIR$/mercurial-tests/mercurial-tests.iml" filepath="$PROJECT_DIR$/mercurial-tests/mercurial-tests.iml" />
+    </modules>
+  </component>
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/runConfigurations/tests.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,38 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="tests" type="TestNG" factoryName="TestNG">
+    <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+    <module name="mercurial-tests" />
+    <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+    <option name="ALTERNATIVE_JRE_PATH" value="" />
+    <option name="SUITE_NAME" value="$PROJECT_DIR$/mercurial-tests/src/testng.xml" />
+    <option name="PACKAGE_NAME" value="" />
+    <option name="MAIN_CLASS_NAME" value="" />
+    <option name="METHOD_NAME" value="" />
+    <option name="GROUP_NAME" value="" />
+    <option name="TEST_OBJECT" value="SUITE" />
+    <option name="VM_PARAMETERS" value="-ea" />
+    <option name="PARAMETERS" value="" />
+    <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+    <option name="OUTPUT_DIRECTORY" value="" />
+    <option name="ANNOTATION_TYPE" />
+    <option name="ENV_VARIABLES" />
+    <option name="PASS_PARENT_ENVS" value="true" />
+    <option name="TEST_SEARCH_SCOPE">
+      <value defaultName="moduleWithDependencies" />
+    </option>
+    <option name="USE_DEFAULT_REPORTERS" value="false" />
+    <option name="PROPERTIES_FILE" value="" />
+    <envs />
+    <properties />
+    <listeners />
+    <RunnerSettings RunnerId="Debug">
+      <option name="DEBUG_PORT" value="51735" />
+      <option name="TRANSPORT" value="0" />
+      <option name="LOCAL" value="true" />
+    </RunnerSettings>
+    <RunnerSettings RunnerId="Run" />
+    <ConfigurationWrapper RunnerId="Debug" />
+    <ConfigurationWrapper RunnerId="Run" />
+    <method />
+  </configuration>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/scopes/scope_settings.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,5 @@
+<component name="DependencyValidationManager">
+  <state>
+    <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+  </state>
+</component>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/uiDesigner.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/vcs.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="hg4idea" />
+  </component>
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/ant.build.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,24 @@
+<project name="build hooks" default="replace-tokens-in-teamcity-plugin-xml" basedir=".">
+
+
+  <target name="replace-tokens-in-teamcity-plugin-xml">
+    <property name="home" value="${artifact.output.path}"/>
+
+    <echo message="replacing tokens in teamcity-plugin.xml file under ${home}"/>
+
+    <condition property="build.number" value="snapshot" else="${build.number}">
+      <not>
+        <isset property="build.number"/>
+      </not>
+    </condition>
+
+    <echo message="Setting version to: ${build.number}"/>
+    <!-- update all references in teamcity-plugin.xml files -->
+    <replace dir="${home}" summary="true">
+      <include name="**/teamcity-plugin.xml"/>
+
+      <replacefilter token="@Plugin_Version@" value="${build.number}"/>
+    </replace>
+  </target>
+
+</project>
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentPluginConfigImpl.java	Mon Mar 18 12:08:16 2013 +0400
@@ -22,7 +22,7 @@
   }
 
   public boolean isUseLocalMirrors(@NotNull AgentRunningBuild build) {
-    return "true".equals(build.getSharedConfigParameters().get("teamcity.hg.use.local.mirrors"));
+    return Boolean.valueOf(build.getSharedConfigParameters().get("teamcity.hg.use.local.mirrors"));
   }
 
   @NotNull
@@ -38,7 +38,7 @@
   }
 
   public boolean runWithTraceback(@NotNull AgentRunningBuild build) {
-    return "true".equals(build.getSharedConfigParameters().get("teamcity.hg.run.commands.with.traceback"));
+    return Boolean.valueOf(build.getSharedConfigParameters().get("teamcity.hg.run.commands.with.traceback"));
   }
 
   @Nullable
--- a/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-agent/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialIncludeRuleUpdater.java	Mon Mar 18 12:08:16 2013 +0400
@@ -159,12 +159,12 @@
       SubRepo workingDirSubrepo = workingDirSubrepos.get(path);
       if (workingDirSubrepo != null && subrepoConfig.hasDifferentUrlThan(workingDirSubrepo)) {
         myLogger.message("The url of subrepoConfig was changed between revisions " + workingDirRevision + " and " + toVersion + " , delete the subrepoConfig");
-        delete(subrepoConfig.dir());
+        delete(subrepoConfigDir(repo, subrepoConfig));
       }
-      HgRepo subrepository = myRepoFactory.create(subrepoConfig.dir(), myHgPath, myAuthSettings);
+      HgRepo subrepository = myRepoFactory.create(subrepoConfigDir(repo, subrepoConfig), myHgPath, myAuthSettings);
       String subrepoUrl;
       try {
-        subrepoUrl = subrepoConfig.isRelative() ? resolveUrl(parentRepositoryUrl, subrepoConfig.url()) : subrepoConfig.url();
+        subrepoUrl = subrepoConfig.resolveUrl(parentRepositoryUrl);
         if (myUseLocalMirrors && subrepoConfig.vcsType() == SubRepo.VcsType.hg && !SubRepo.isRelativeUrl(subrepoUrl))
           syncSubrepo(subrepository, subrepoUrl, subrepoConfig.revision());
       } catch (URISyntaxException e) {
@@ -175,14 +175,6 @@
     }
   }
 
-  private String resolveUrl(@NotNull String parentRepoUrl, @NotNull String relativeUrl) throws URISyntaxException {
-    if (!parentRepoUrl.endsWith("/"))
-      parentRepoUrl = parentRepoUrl + "/";
-    URI parentURI = new URI(parentRepoUrl);
-    URI subrepoAbsUrl = parentURI.resolve(relativeUrl);
-    return subrepoAbsUrl.toString();
-  }
-
   private void syncSubrepo(@NotNull HgRepo subrepository, @NotNull String url, @NotNull String revision) throws VcsException, IOException {
     if (!subrepository.isValidRepository() || !subrepository.containsRevision(revision)) {
       updateLocalMirror(url, revision);
@@ -239,4 +231,8 @@
     else
       throw new VcsException(e);
   }
+
+  private File subrepoConfigDir(@NotNull HgRepo parentRepo, @NotNull SubRepo subrepo) {
+    return new File(parentRepo.getWorkingDir(), subrepo.path());
+  }
 }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java	Mon Mar 18 12:08:16 2013 +0400
@@ -28,4 +28,5 @@
   String PASSWORD = VcsRoot.SECURE_PROPERTY_PREFIX + "password";
   String UNCOMPRESSED_TRANSFER = "uncompressedTransfer";
   String USER_FOR_TAG = "tagUsername";
+  String DETECT_SUBREPO_CHANGES = "detectSubrepoChanges";
 }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java	Mon Mar 18 12:08:16 2013 +0400
@@ -10,6 +10,7 @@
 import java.io.IOException;
 import java.util.*;
 
+import static java.util.Collections.emptyList;
 import static java.util.Collections.emptyMap;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.HgFileUtil.deleteDir;
 import static jetbrains.buildServer.util.FileUtil.isEmptyDir;
@@ -67,6 +68,10 @@
     return new BranchesCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings);
   }
 
+  public BookmarksCommand bookmarks() {
+    return new BookmarksCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings);
+  }
+
   public StatusCommand status() {
     return new StatusCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings);
   }
@@ -87,6 +92,10 @@
     return new VersionCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir);
   }
 
+  public ParentsCommand parents() {
+    return new ParentsCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir);
+  }
+
   public String path() {
     return myWorkingDir.getAbsolutePath();
   }
@@ -99,6 +108,16 @@
     return isEmptyDir(myWorkingDir);
   }
 
+  public void resetBookmarks() {
+    File dotHg = new File(getWorkingDir(), ".hg");
+    FileUtil.delete(new File(dotHg, "bookmarks"));
+    FileUtil.delete(new File(dotHg, "bookmarks.current"));
+  }
+
+  public String getHgPath() {
+    return myHgPath;
+  }
+
   @NotNull
   public List<String> listFiles(@NotNull String revision) throws VcsException {
     List<FileStatus> fileStatuses = status()
@@ -157,11 +176,91 @@
     return getSubrepositories(new ChangeSet(revision));
   }
 
+  public List<HgSubrepoConfigChange> getSubrepoConfigChanges(@NotNull String revision) throws VcsException {
+    if (containsSubrepoConfigChange(revision)) {
+      List<String> parents = parents().ofRevision(revision).call();
+      return getSubrepoConfigChanges(revision, parents);
+    }
+    return emptyList();
+  }
+
+  public List<HgSubrepoConfigChange> getSubrepoConfigChanges(@NotNull ChangeSet cset) {
+    if (containsSubrepoConfigChange(cset)) {
+      List<String> parents = new ArrayList<String>();
+      for (ChangeSetRevision p : cset.getParents()) {
+        parents.add(p.getId());
+      }
+      return getSubrepoConfigChanges(cset.getId(), parents);
+    }
+    return emptyList();
+  }
+
+  private List<HgSubrepoConfigChange> getSubrepoConfigChanges(@NotNull String revision, @NotNull List<String> parentRevisions) {
+    Map<String, SubRepo> curSubrepos = getSubrepositories(revision);
+    List<Map<String, SubRepo>> prevSubrepos = new ArrayList<Map<String, SubRepo>>();
+    for (String parentRevision : parentRevisions) {
+      prevSubrepos.add(getSubrepositories(parentRevision));
+    }
+    return getSubrepoConfigChanges(prevSubrepos, curSubrepos);
+
+  }
+
+  private List<HgSubrepoConfigChange> getSubrepoConfigChanges(@NotNull List<Map<String, SubRepo>> prevSubrepos,
+                                                              @NotNull Map<String, SubRepo> curSubrepos) {
+    List<HgSubrepoConfigChange> configChanges = new ArrayList<HgSubrepoConfigChange>();
+    for (Map.Entry<String, SubRepo> e : curSubrepos.entrySet()) {
+      String path = e.getKey();
+      SubRepo curSubrepo = e.getValue();
+      List<SubRepo> prevs = new ArrayList<SubRepo>();
+      for (Map<String, SubRepo> prev : prevSubrepos) {
+        SubRepo prevSubrepo = prev.remove(path);
+        if (prevSubrepo == null) //no subrepo at this path in previous revision
+          continue;
+        if (prevSubrepo.equals(curSubrepo)) //subrepo configuration doesn't change since previous revision
+          continue;
+        prevs.add(prevSubrepo);
+      }
+      configChanges.add(new HgSubrepoConfigChange(e.getKey(), prevs, curSubrepo));
+    }
+    for (Map<String, SubRepo> prev : prevSubrepos) {
+      for (Map.Entry<String, SubRepo> e : prev.entrySet()) {
+        configChanges.add(new HgSubrepoConfigChange(e.getKey(), e.getValue(), null));
+      }
+    }
+    return configChanges;
+  }
+
+  private boolean containsSubrepoConfigChange(@NotNull ChangeSet cset) {
+    for (FileStatus f : cset.getModifiedFiles()) {
+      if (containsSubrepoConfigChange(f))
+        return true;
+    }
+    return false;
+  }
+
+  private boolean containsSubrepoConfigChange(@NotNull String revision) throws VcsException {
+    List<FileStatus> changedFiles = status()
+            .fromRevision(revision)
+            .toRevision(revision)
+            .showAllFiles()
+            .call();
+    for (FileStatus f : changedFiles) {
+      if (containsSubrepoConfigChange(f))
+        return true;
+    }
+    return false;
+  }
+
+  private boolean containsSubrepoConfigChange(@NotNull FileStatus f) {
+    return f.getPath().equals(".hgsubstate");
+  }
+
+  //path->subrepo
   public Map<String, SubRepo> getSubrepositories(@NotNull ChangeSet cset) {
     String revId = cset.getId();
     Map<String, SubRepo> subrepos = mySubreposCache.get(revId);
     if (subrepos != null)
-      return subrepos;
+      return new HashMap<String, SubRepo>(subrepos);
     CatCommand cc = cat();
     cc.setRevId(revId);
     File catDir = null;
@@ -171,7 +270,7 @@
       File hgsubstate = new File(catDir, ".hgsubstate");
       subrepos = readSubrepositories(hgsub, hgsubstate);
       mySubreposCache.put(revId, subrepos);
-      return subrepos;
+      return new HashMap<String, SubRepo>(subrepos);
     } catch (VcsException e) {
       return emptyMap();
     } finally {
@@ -179,10 +278,6 @@
     }
   }
 
-  public String getHgPath() {
-    return myHgPath;
-  }
-
   @Override
   public String toString() {
     return myWorkingDir.getAbsolutePath();
@@ -198,15 +293,11 @@
           String path = entry.getKey();
           String url = entry.getValue();
           String revision = path2revision.get(path);
-          if (revision != null) {
-            result.put(path, new SubRepo(this, path, url, revision));
-          } else {
-//              myLogger.warning("Cannot find revision for subrepository at path " + path + " skip it");
-          }
+          if (revision != null)
+            result.put(path, new SubRepo(path, url, revision));
         }
         return result;
       } catch (IOException e) {
-//          myLogger.warning("Error while trying to read subrepositories " + e.getMessage());
         return emptyMap();
       }
     } else {
@@ -219,11 +310,8 @@
     Map<String, String> result = new HashMap<String, String>();
     for (String line : FileUtil.readFile(hgsub)) {
       String[] parts = line.split(" = ");
-      if (parts.length == 2) {
+      if (parts.length == 2)
         result.put(parts[0], parts[1]);
-      } else {
-//          myLogger.warning("Cannot parse the line '" + line + "' from .hgsub, skip it");
-      }
     }
     return result;
   }
@@ -234,11 +322,8 @@
     Map<String, String> result = new HashMap<String, String>();
     for (String line : FileUtil.readFile(hgsubstate)) {
       String[] parts = line.split(" ");
-      if (parts.length == 2) {
+      if (parts.length == 2)
         result.put(parts[1], parts[0]);
-      } else {
-//          myLogger.warning("Cannot parse the line '" + line + "' from .hgsubstate, skip it");
-      }
     }
     return result;
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgSubrepoConfigChange.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,67 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+
+/**
+ * A change in subrepo configuration
+ */
+public class HgSubrepoConfigChange {
+
+  private final String myPath;
+  private final SubRepo myCurrent;
+  private final List<SubRepo> myPrevious;
+
+  public HgSubrepoConfigChange(@NotNull String path,
+                               @Nullable SubRepo previous,
+                               @Nullable SubRepo current) {
+    this(path, previous != null ? asList(previous) : new ArrayList<SubRepo>(), current);
+  }
+
+  public HgSubrepoConfigChange(@NotNull String path,
+                               @NotNull List<SubRepo> previous,
+                               @Nullable SubRepo current) {
+    myPath = path;
+    myPrevious = previous;
+    myCurrent = current;
+  }
+
+  @NotNull
+  public String getPath() {
+    return myPath;
+  }
+
+  @NotNull
+  public List<SubRepo> getPrevious() {
+    return myPrevious;
+  }
+
+  public SubRepo getCurrent() {
+    return myCurrent;
+  }
+
+  public boolean subrepoRemoved() {
+    return myCurrent == null && !myPrevious.isEmpty();
+  }
+
+  public boolean subrepoAdded() {
+    return myCurrent != null && myPrevious.isEmpty();
+  }
+
+  public boolean subrepoUrlChanged() {
+    if (myCurrent == null)
+      return false;
+    if (myPrevious.isEmpty())
+      return false;
+    for (SubRepo sr : myPrevious) {
+      if (!myCurrent.url().equals(sr.url()))
+        return true;
+    }
+    return false;
+  }
+}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubRepo.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubRepo.java	Mon Mar 18 12:08:16 2013 +0400
@@ -2,20 +2,19 @@
 
 import org.jetbrains.annotations.NotNull;
 
-import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
 
 /**
 * @author dmitry.neverov
 */
 public class SubRepo {
-  private final HgRepo myParentRepo;
   private final String myPath;
   private final String myUrl;
   private final String myRevision;
   private final VcsType myVcsType;
 
-  public SubRepo(@NotNull HgRepo parentRepo, @NotNull String path, @NotNull String url, @NotNull String revision) {
-    myParentRepo = parentRepo;
+  public SubRepo(@NotNull String path, @NotNull String url, @NotNull String revision) {
     myPath = path;
     myUrl = url;
     myRevision = revision;
@@ -34,6 +33,8 @@
 
   @NotNull
   public String revision() {
+    if (myRevision.length() > 12)
+      return myRevision.substring(0, 12);
     return myRevision;
   }
 
@@ -50,13 +51,22 @@
     return url.startsWith("..");
   }
 
-  @NotNull
-  File dir() {
-    return new File(myParentRepo.getWorkingDir(), myPath);
+  public boolean hasDifferentUrlThan(@NotNull SubRepo other) {
+    return !myUrl.equals(other.url());
   }
 
-  public boolean hasDifferentUrlThan(@NotNull SubRepo other) {
-    return !myUrl.equals(other.url());
+  public String resolveUrl(@NotNull String parentRepoUrl) throws URISyntaxException {
+    if (!isRelative())
+      return url();
+    if (!parentRepoUrl.endsWith("/"))
+      parentRepoUrl = parentRepoUrl + "/";
+    try {
+      URI parentURI = new URI(parentRepoUrl);
+      URI subrepoAbsUrl = parentURI.resolve(url());
+      return subrepoAbsUrl.toString();
+    } catch (URISyntaxException e) {
+      return parentRepoUrl + url();
+    }
   }
 
   @Override
@@ -75,4 +85,31 @@
   public static enum VcsType {
     hg, git, svn
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o)
+      return true;
+    if (!(o instanceof SubRepo))
+      return false;
+
+    SubRepo subRepo = (SubRepo) o;
+
+    if (!myPath.equals(subRepo.myPath))
+      return false;
+    if (!myRevision.equals(subRepo.myRevision))
+      return false;
+    if (!myUrl.equals(subRepo.myUrl))
+      return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myPath.hashCode();
+    result = 31 * result + myUrl.hashCode();
+    result = 31 * result + myRevision.hashCode();
+    return result;
+  }
 }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommand.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommand.java	Mon Mar 18 12:08:16 2013 +0400
@@ -15,6 +15,7 @@
  */
 package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
 
+import jetbrains.buildServer.vcs.VcsException;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
@@ -58,6 +59,10 @@
     return cl;
   }
 
+  protected CommandResult runCommand(@NotNull MercurialCommandLine cli) throws VcsException {
+    return CommandUtil.runCommand(cli, myCommandSettings);
+  }
+
   protected Set<String> getPrivateData() {
     return emptySet();
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BookmarksCommand.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,25 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
+
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgVersion;
+import org.jetbrains.annotations.NotNull;
+import java.io.File;
+
+
+public class BookmarksCommand extends BranchesCommand {
+
+  //hg 2.4 automatically pulls bookmarks
+  public static final HgVersion REQUIRED_HG_VERSION = new HgVersion(2, 4, 0);
+
+  public BookmarksCommand(@NotNull CommandSettings commandSettings,
+                          @NotNull String hgPath,
+                          @NotNull File workingDir,
+                          @NotNull AuthSettings authSettings) {
+    super(commandSettings, hgPath, workingDir, authSettings);
+  }
+
+  @NotNull
+  @Override
+  protected String getBranchesCommand() {
+    return "bookmarks";
+  }
+}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BranchesCommand.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BranchesCommand.java	Mon Mar 18 12:08:16 2013 +0400
@@ -42,21 +42,26 @@
    * @return see above
    * @throws jetbrains.buildServer.vcs.VcsException if error occurs
    */
-  public Map<String, ChangeSet> call() throws VcsException {
+  public Map<String, String> call() throws VcsException {
     MercurialCommandLine cli = createCommandLine();
-    cli.addParameter("branches");
+    cli.addParameter(getBranchesCommand());
     CommandResult res = runCommand(cli);
     String stdout = res.getStdout();
-    Map<String, ChangeSet> result = new HashMap<String, ChangeSet>();
+    Map<String, String> result = new HashMap<String, String>();
     Pattern branchPattern = Pattern.compile("(.*)[\\s]+([0-9]+:[A-Za-z0-9]+).*");
     for (String line: stdout.split("[\r\n]+")) {
       Matcher matcher = branchPattern.matcher(line);
       if (matcher.matches()) {
         String branchName = matcher.group(1).trim();
         String changeId = matcher.group(2).trim();
-        result.put(branchName, new ChangeSet(changeId));
+        result.put(branchName, new ChangeSet(changeId).getId());
       }
     }
     return result;
   }
+
+  @NotNull
+  protected String getBranchesCommand() {
+    return "branches";
+  }
 }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java	Mon Mar 18 12:08:16 2013 +0400
@@ -41,7 +41,7 @@
                                    @NotNull final String command,
                                    @NotNull final Set<String> privateData) {
     final long start = System.currentTimeMillis();
-    ExecResult res = SimpleCommandLineProcessRunner.runCommand(cli, null, new SimpleCommandLineProcessRunner.RunCommandEventsAdapter() {
+    ExecResult res = SimpleCommandLineProcessRunner.runCommand(cli, null, new SimpleCommandLineProcessRunner.ProcessRunCallbackAdapter() {
       @Override
       public Integer getOutputIdleSecondsTimeout() {
         return executionTimeout;
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Mon Mar 18 12:08:16 2013 +0400
@@ -15,16 +15,16 @@
  */
 package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
 
+import java.io.File;
+import java.util.Map;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.Constants;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.PathUtil;
 import jetbrains.buildServer.util.StringUtil;
 import jetbrains.buildServer.vcs.VcsRoot;
+import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.io.File;
-import java.util.Map;
-
 /**
  * Represents mercurial VCS root
  */
@@ -41,16 +41,22 @@
   private final String myUserForTag;
   private final AuthSettings myAuthSettings;
   private File myCustomWorkingDir;
+  private final boolean myDetectSubrepoChanges;
 
   public HgVcsRoot(@NotNull final VcsRoot vcsRoot) {
+    this(vcsRoot, vcsRoot.getProperty(Constants.REPOSITORY_PROP));
+  }
+
+  public HgVcsRoot(@NotNull VcsRoot vcsRoot, @NotNull String repository) {
     myRoot = vcsRoot;
-    myRepository = getProperty(Constants.REPOSITORY_PROP);
+    myRepository = repository;
     myHgCommandPath = getProperty(Constants.HG_COMMAND_PATH_PROP);
     myBranchName = getProperty(Constants.BRANCH_NAME_PROP);
     myCustomClonePath = getProperty(Constants.SERVER_CLONE_PATH_PROP);
     myUncompressedTransfer = "true".equals(getProperty(Constants.UNCOMPRESSED_TRANSFER));
     myUserForTag = getProperty(Constants.USER_FOR_TAG);
     myAuthSettings = new AuthSettings(getProperty(Constants.USERNAME), getProperty(Constants.PASSWORD));
+    myDetectSubrepoChanges = Boolean.parseBoolean(getProperty(Constants.DETECT_SUBREPO_CHANGES));
   }
 
   public String getCustomClonePath() {
@@ -61,6 +67,10 @@
     return myRepository;
   }
 
+  public HgVcsRoot withUrl(@NotNull String repositoryUrl) {
+    return new HgVcsRoot(this, repositoryUrl);
+  }
+
   /**
    * Returns name of the branch to use (returns 'default' if no branch specified)
    * @return see above
@@ -112,6 +122,9 @@
     return myAuthSettings;
   }
 
+  public boolean detectSubrepoChanges() {
+    return myDetectSubrepoChanges;
+  }
 
 
   public String getVcsName() {
@@ -119,6 +132,8 @@
   }
 
   public String getProperty(String propertyName) {
+    if (Constants.REPOSITORY_PROP.equals(propertyName) && myRepository != null)
+      return myRepository;
     return myRoot.getProperty(propertyName);
   }
 
@@ -154,11 +169,8 @@
     return myRoot.getPublicProperties();
   }
 
-  public String getSimplifiedName() {
-    return myRoot.getSimplifiedName();
-  }
-
-  public VcsRoot getOriginalRoot() {
-    return myRoot;
+  @NotNull
+  public String describe(final boolean verbose) {
+    return myRoot.describe(verbose);
   }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ParentsCommand.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,38 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
+
+import jetbrains.buildServer.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ParentsCommand extends BaseCommand {
+
+  private String myRevision;
+
+  public ParentsCommand(@NotNull CommandSettings commandSettings,
+                        @NotNull String hgPath,
+                        @NotNull File workingDir) {
+    super(commandSettings, hgPath, workingDir);
+  }
+
+  public ParentsCommand ofRevision(@NotNull String revision) {
+    myRevision = revision;
+    return this;
+  }
+
+  public List<String> call() throws VcsException {
+    MercurialCommandLine cli = createCommandLine();
+    cli.addParameter("parents");
+    cli.addParameter("-q");
+    if (myRevision != null)
+      cli.addParameters("-r", myRevision);
+    CommandResult res = runCommand(cli);
+    List<String> parentRevisions = new ArrayList<String>();
+    for (String line : res.getStdout().split("\n")) {
+      parentRevisions.add(new ChangeSet(line).getId());
+    }
+    return parentRevisions;
+  }
+}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/VcsRootCommand.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/VcsRootCommand.java	Mon Mar 18 12:08:16 2013 +0400
@@ -23,10 +23,6 @@
   }
 
 
-  protected CommandResult runCommand(@NotNull MercurialCommandLine cli) throws VcsException {
-    return CommandUtil.runCommand(cli, myCommandSettings);
-  }
-
   protected CommandResult runCommand(@NotNull MercurialCommandLine cli, @NotNull CommandSettings s) throws VcsException {
     s.setPrivateData(getPrivateData());
     return CommandUtil.runCommand(cli, s);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server-tc/mercurial-server-tc.iml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="TeamCity Vcs Api" level="project" />
+    <orderEntry type="library" name="TeamCityAPI-server" level="project" />
+    <orderEntry type="module" module-name="mercurial-server" />
+    <orderEntry type="library" name="TeamCityAPI-common" level="project" />
+    <orderEntry type="module" module-name="mercurial-common" />
+  </component>
+</module>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server-tc/src/META-INF/build-server-plugin-mercurial-tc.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans default-autowire="constructor">
+    <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialExtensionRegistry"/>
+    <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialBranchSupport"/>
+    <bean class="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialCleaner"/>
+</beans>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialBranchSupport.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,12 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import jetbrains.buildServer.vcs.*;
+import org.jetbrains.annotations.NotNull;
+
+
+public class MercurialBranchSupport implements BranchSupport, MercurialServerExtension {
+  @NotNull
+  public String getRemoteRunOnBranchPattern() {
+    return "remote-run/*";
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCleaner.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,24 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import jetbrains.buildServer.serverSide.BuildServerAdapter;
+import jetbrains.buildServer.serverSide.BuildServerListener;
+import jetbrains.buildServer.serverSide.SBuildServer;
+import jetbrains.buildServer.util.EventDispatcher;
+import jetbrains.buildServer.vcs.VcsManager;
+import org.jetbrains.annotations.NotNull;
+
+public class MercurialCleaner implements MercurialServerExtension {
+
+  public MercurialCleaner(@NotNull final SBuildServer server,
+                          @NotNull final VcsManager vcsManager,
+                          @NotNull final EventDispatcher<BuildServerListener> dispatcher,
+                          @NotNull final ServerPluginConfig config,
+                          @NotNull final MirrorManager mirrorManager) {
+    dispatcher.addListener(new BuildServerAdapter() {
+      @Override
+      public void cleanupFinished() {
+        server.getExecutor().submit(new Cleanup(vcsManager, mirrorManager, config));
+      }
+    });
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialExtensionRegistry.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,13 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class MercurialExtensionRegistry {
+
+  public MercurialExtensionRegistry(@NotNull MercurialVcsSupport vcs,
+                                    @NotNull Collection<MercurialServerExtension> extensions) {
+    vcs.setExtensions(extensions);
+  }
+}
--- a/mercurial-server/mercurial-server.iml	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/mercurial-server.iml	Mon Mar 18 12:08:16 2013 +0400
@@ -19,6 +19,7 @@
     <orderEntry type="library" exported="" name="IDEA-openapi" level="project" />
     <orderEntry type="library" exported="" name="Log4j" level="project" />
     <orderEntry type="module" module-name="mercurial-common" />
+    <orderEntry type="library" name="TeamCity Vcs Api" level="project" />
   </component>
 </module>
 
--- a/mercurial-server/resources/buildServerResources/mercurialSettings.jsp	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/resources/buildServerResources/mercurialSettings.jsp	Mon Mar 18 12:08:16 2013 +0400
@@ -31,6 +31,12 @@
     </td>
   </tr>
   <tr>
+    <th><label for="detectSubrepoChanges">Detect subrepo changes: </label></th>
+      <td>
+        <props:checkboxProperty name="detectSubrepoChanges"/>
+      </td>
+    </tr>
+  <tr>
     <th><label for="tagUsername">Username For Tags: </label></th>
     <td><props:textProperty name="tagUsername"/>
       <div class="smallNote" style="margin: 0;">Format: User Name &lt;email&gt;</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,389 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnknownRevisionException;
+import jetbrains.buildServer.log.Loggers;
+import jetbrains.buildServer.serverSide.impl.LogUtil;
+import jetbrains.buildServer.vcs.*;
+import jetbrains.buildServer.vcs.impl.VcsRootImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.net.URISyntaxException;
+import java.util.*;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptyMap;
+
+public class MercurialCollectChangesPolicy implements CollectChangesBetweenRoots, CollectChangesBetweenRepositories {
+
+  private final MercurialVcsSupport myVcs;
+  private final ServerPluginConfig myConfig;
+  private final HgVcsRootFactory myHgVcsRootFactory;
+  private final RepoFactory myRepoFactory;
+  private final HgPathProvider myHgPathProvider;
+
+
+  public MercurialCollectChangesPolicy(@NotNull MercurialVcsSupport vcs,
+                                       @NotNull ServerPluginConfig config,
+                                       @NotNull HgVcsRootFactory hgVcsRootFactory,
+                                       @NotNull RepoFactory repoFactory,
+                                       @NotNull HgPathProvider hgPathProvider) {
+    myVcs = vcs;
+    myConfig = config;
+    myHgVcsRootFactory = hgVcsRootFactory;
+    myRepoFactory = repoFactory;
+    myHgPathProvider = hgPathProvider;
+  }
+
+
+  @NotNull
+  public RepositoryStateData getCurrentState(@NotNull VcsRoot root) throws VcsException {
+    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
+    myVcs.syncRepository(hgRoot);
+    Map<String, String> revisions = new HashMap<String, String>();
+    revisions.putAll(getBookmarkRevisions(hgRoot));
+    revisions.putAll(getBranchesRevisions(hgRoot));
+    String defaultBranchName = hgRoot.getBranchName();
+    if (revisions.get(defaultBranchName) == null) {
+      throw new VcsException("Cannot find revision of the default branch '" +
+              defaultBranchName + "' of vcs root " + LogUtil.describe(root));
+    }
+    return RepositoryStateData.createVersionState(defaultBranchName, revisions);
+  }
+
+
+  @NotNull
+  private Map<String, String> getBranchesRevisions(@NotNull HgVcsRoot root) throws VcsException {
+    HgRepo repo = myVcs.createRepo(root);
+    return repo.branches().call();
+  }
+
+
+  @NotNull
+  private Map<String, String> getBookmarkRevisions(@NotNull HgVcsRoot root) throws VcsException {
+    ServerHgRepo repo = myVcs.createRepo(root);
+    if (!myConfig.bookmarksEnabled())
+      return emptyMap();
+    HgVersion version = repo.version().call();
+    if (!version.isEqualsOrGreaterThan(BookmarksCommand.REQUIRED_HG_VERSION))
+      return emptyMap();
+    return repo.bookmarks().call();
+  }
+
+
+  @NotNull
+  public List<ModificationData> collectChanges(@NotNull VcsRoot fromRoot,
+                                               @NotNull RepositoryStateData fromState,
+                                               @NotNull VcsRoot toRoot,
+                                               @NotNull RepositoryStateData toState,
+                                               @NotNull CheckoutRules rules) throws VcsException {
+    return collectChanges(toRoot, fromState, toState, rules);
+  }
+
+
+  @NotNull
+  public List<ModificationData> collectChanges(@NotNull VcsRoot root,
+                                               @NotNull RepositoryStateData fromState,
+                                               @NotNull RepositoryStateData toState,
+                                               @NotNull CheckoutRules rules) throws VcsException {
+    List<ModificationData> changes = new ArrayList<ModificationData>();
+    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
+    OperationContext ctx = new OperationContext(myVcs, myRepoFactory, myHgPathProvider, fromState, toState);
+    for (Map.Entry<String, String> entry : toState.getBranchRevisions().entrySet()) {
+      String branch = entry.getKey();
+      String toRevision = entry.getValue();
+      String fromRevision = fromState.getBranchRevisions().get(branch);
+      if (fromRevision == null)
+        fromRevision = fromState.getBranchRevisions().get(fromState.getDefaultBranchName());
+      if (toRevision.equals(fromRevision) || fromRevision == null)
+        continue;
+
+      Collection<String> fromRevisions = ctx.getFromRevisionsForBranch(hgRoot, fromRevision, toRevision);
+      List<ModificationData> branchChanges = collectChanges(ctx, root, fromRevisions, toRevision, rules);
+      for (ModificationData change : branchChanges) {
+        if (!ctx.isReportedModification(change)) {
+          changes.add(change);
+          ctx.markAsReported(change);
+        }
+      }
+    }
+    changes.addAll(getSubrepoChanges(ctx, root, changes));
+    return changes;
+  }
+
+
+  @NotNull
+  public List<ModificationData> collectChanges(@NotNull VcsRoot fromRoot,
+                                               @NotNull String fromRootRevision,
+                                               @NotNull VcsRoot toRoot,
+                                               @Nullable String toRootRevision,
+                                               @NotNull CheckoutRules checkoutRules) throws VcsException {
+    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(toRoot);
+    myVcs.syncRepository(hgRoot);
+    String toRevision = toRootRevision != null ? toRootRevision : myVcs.getCurrentVersion(toRoot);
+    String mergeBase = getMergeBase(hgRoot, fromRootRevision, toRevision);
+    if (mergeBase == null)
+      return Collections.emptyList();
+    return collectChanges(toRoot, mergeBase, toRootRevision, checkoutRules);
+  }
+
+
+  public List<ModificationData> collectChanges(@NotNull VcsRoot root,
+                                               @NotNull String fromVersion,
+                                               @Nullable String currentVersion,
+                                               @NotNull CheckoutRules checkoutRules) throws VcsException {
+    if (currentVersion == null)
+      return emptyList();
+    OperationContext ctx = new OperationContext(myVcs, myRepoFactory, myHgPathProvider, fromVersion, currentVersion);
+    List<ModificationData> changes = collectChanges(ctx, root, asList(fromVersion), currentVersion, checkoutRules);
+    changes.addAll(getSubrepoChanges(ctx, root, changes));
+    return changes;
+  }
+
+
+  @Nullable
+  private String getMergeBase(@NotNull HgVcsRoot root, @NotNull String revision1, @NotNull String revision2) throws VcsException {
+    String result = myVcs.createRepo(root).mergeBase()
+            .revision1(revision1)
+            .revision2(revision2)
+            .call();
+    if (result == null)
+      result = getMinusNthCommit(root, 10);
+    return result;
+  }
+
+
+  @Nullable
+  private String getMinusNthCommit(@NotNull HgVcsRoot root, int n) throws VcsException {
+    LogCommand log = myVcs.createRepo(root).log()
+            .inBranch(root.getBranchName())
+            .toNamedRevision(root.getBranchName());
+    if (n > 0)
+      log.setLimit(n);
+    List<ChangeSet> changeSets = log.call();
+    if (changeSets.isEmpty())
+      return null;
+    return changeSets.get(0).getId();
+  }
+
+
+  private List<ModificationData> collectChanges(@NotNull OperationContext ctx,
+                                                @NotNull VcsRoot root,
+                                                @NotNull Collection<String> fromVersion,
+                                                @Nullable String currentVersion,
+                                                @NotNull CheckoutRules checkoutRules) throws VcsException {
+    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
+    ctx.syncRepository(hgRoot);
+    List<ModificationData> result = new ArrayList<ModificationData>();
+    for (ChangeSet cset : getChangesets(ctx, hgRoot, fromVersion, currentVersion)) {
+      result.add(createModificationData(ctx, cset, root, checkoutRules));
+    }
+    return result;
+  }
+
+
+  @NotNull
+  private List<ChangeSet> getChangesets(@NotNull OperationContext ctx,
+                                        @NotNull final HgVcsRoot root,
+                                        @NotNull final Collection<String> fromVersions,
+                                        @Nullable final String toVersion) throws VcsException {
+    if (toVersion == null)
+      return emptyList();
+    List<String> fromCommits = new ArrayList<String>();
+    for (String fromVersion : fromVersions) {
+      fromCommits.add(new ChangeSetRevision(fromVersion).getId());
+    }
+    String toCommit = new ChangeSetRevision(toVersion).getId();
+    try {
+      ServerHgRepo repo = myVcs.createRepo(ctx, root);
+      List<ChangeSet> csets = repo.collectChanges(root)
+              .fromRevision(fromCommits)
+              .toRevision(toCommit)
+              .includeFromRevision(ctx.includeFromRevisions())
+              .call();
+      if (!ctx.includeFromRevisions()) {
+        Iterator<ChangeSet> iter = csets.iterator();
+        while (iter.hasNext()) {
+          ChangeSet cset = iter.next();
+          if (fromVersions.contains(cset.getId()))
+            iter.remove();
+        }
+      }
+      return csets;
+    } catch (UnknownRevisionException e) {
+      Loggers.VCS.warn("Revision '" + e.getRevision() + "' is unknown, will return no changes");
+      return emptyList();
+    }
+  }
+
+
+  private ModificationData createModificationData(@NotNull OperationContext ctx,
+                                                  @NotNull final ChangeSet cset,
+                                                  @NotNull final VcsRoot root,
+                                                  @NotNull final CheckoutRules checkoutRules) throws VcsException {
+    List<ChangeSetRevision> parents = cset.getParents();
+    if (parents.isEmpty())
+      throw new IllegalStateException("Commit " + cset.getId() + " has no parents");
+    List<VcsChange> files = toVcsChanges(cset.getModifiedFiles(), parents.get(0).getId(), cset.getId(), checkoutRules);
+    final ModificationData result = new ModificationData(cset.getTimestamp(), files, cset.getDescription(), cset.getUser(), root, cset.getId(), cset.getId());
+    for (ChangeSetRevision parent : parents) {
+      result.addParentRevision(parent.getId());
+    }
+    setCanBeIgnored(result, cset);
+    result.setAttributes(getAttributes(ctx, root, cset));
+    return result;
+  }
+
+
+  private void setCanBeIgnored(@NotNull ModificationData md, @NotNull ChangeSet cset) {
+    if (md.getParentRevisions().size() > 1) {
+      //don't ignore merge commits
+      md.setCanBeIgnored(false);
+    } else if (cset.getModifiedFiles().isEmpty()) {
+      //don't ignore empty commits
+      md.setCanBeIgnored(false);
+    }
+  }
+
+
+  private List<VcsChange> toVcsChanges(final List<FileStatus> modifiedFiles, String prevVer, String curVer, CheckoutRules rules) {
+    List<VcsChange> files = new ArrayList<VcsChange>();
+    for (FileStatus mf: modifiedFiles) {
+      final String path = rules.map(mf.getPath());
+      if (shouldInclude(path))
+        files.add(toVcsChange(mf, prevVer, curVer, path));
+    }
+    return files;
+  }
+
+
+  private boolean shouldInclude(String path) {
+    return path != null;
+  }
+
+
+  private VcsChange toVcsChange(FileStatus mf, String prevVer, String curVer, String mappedPath) {
+    String normalizedPath = PathUtil.normalizeSeparator(mf.getPath());
+    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;
+    }
+    return new VcsChange(changeType, mf.getStatus().getName(), normalizedPath, mappedPath, prevVer, curVer);
+  }
+
+
+  private VcsChangeInfo.Type getChangeType(final 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
+  private List<ModificationData> getSubrepoChanges(@NotNull OperationContext ctx, @NotNull VcsRoot root, @NotNull List<ModificationData> changes) throws VcsException {
+    if (changes.isEmpty())
+      return emptyList();
+
+    ctx.setIncludeFromRevisions(true);
+
+    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
+    if (!detectSubrepoChanges(hgRoot))
+      return emptyList();
+
+    List<SubrepoConfigChange> subrepoConfigChanges = getSubrepoConfigChanges(changes);
+    List<ModificationData> subrepoChanges = new ArrayList<ModificationData>();
+
+    for (SubrepoConfigChange configChange : subrepoConfigChanges) {
+      VcsRootImpl subrepo = new VcsRootImpl(root.getId(), configChange.getSubrepoRootParams());
+      if (ctx.isProcessedSubrepoChanges(subrepo, configChange.getPreviousSubrepoRevisions(), configChange.getCurrentSubrepoRevision()))
+        continue;
+      List<ModificationData> subChanges = collectChanges(ctx, subrepo, configChange.getPreviousSubrepoRevisions(), configChange.getCurrentSubrepoRevision(), CheckoutRules.DEFAULT);
+      for (ModificationData m : subChanges) {
+        if (!ctx.isReportedModification(m)) {
+          subrepoChanges.add(m);
+          ctx.markAsReported(m);
+        }
+      }
+      ctx.markProcessedSubrepoChanges(subrepo, configChange.getPreviousSubrepoRevisions(), configChange.getCurrentSubrepoRevision());
+    }
+
+    List<ModificationData> subSubrepoChanges = getSubrepoChanges(ctx, root, subrepoChanges);
+    subrepoChanges.addAll(subSubrepoChanges);
+    return subrepoChanges;
+  }
+
+
+  private boolean detectSubrepoChanges(@NotNull HgVcsRoot root) {
+    return myConfig.detectSubrepoChanges() && root.detectSubrepoChanges();
+  }
+
+
+  private List<SubrepoConfigChange> getSubrepoConfigChanges(@NotNull List<ModificationData> mainRootChanges) {
+    List<SubrepoConfigChange> subrepoConfigChanges = new ArrayList<SubrepoConfigChange>();
+    for (ModificationData m : mainRootChanges) {
+      subrepoConfigChanges.addAll(getSubrepoConfigChanges(m));
+    }
+    return subrepoConfigChanges;
+  }
+
+
+  private List<SubrepoConfigChange> getSubrepoConfigChanges(@NotNull ModificationData m) {
+    List<SubrepoConfigChange> configChanges = new ArrayList<SubrepoConfigChange>();
+    for (SubrepoConfigChange configChange : SubrepoConfigChangesAttributes.readSubrepoConfigChanges(m.getAttributes())) {
+      if (configChange.getSubrepoRootParams().isEmpty())
+        continue;
+      if (configChange.getPreviousSubrepoRevisions().isEmpty())
+        continue;
+      configChanges.add(configChange);
+    }
+    return configChanges;
+  }
+
+
+  @NotNull
+  private Map<String, String> getAttributes(@NotNull OperationContext ctx, @NotNull VcsRoot mainRoot, @NotNull ChangeSet cset) throws VcsException {
+    Map<String, String> attributes = new HashMap<String, String>();
+    HgVcsRoot root = myHgVcsRootFactory.createHgRoot(mainRoot);
+    if (detectSubrepoChanges(root)) {
+      try {
+        ServerHgRepo repo = myVcs.createRepo(ctx, root);
+        SubrepoConfigChangesAttributes builder = new SubrepoConfigChangesAttributes();
+        for (HgSubrepoConfigChange c : repo.getSubrepoConfigChanges(cset)) {
+          fillSubrepoConfigChanges(builder, root, c);
+        }
+        attributes.putAll(builder.buildAttributes());
+      } catch (Exception e) {
+        Loggers.VCS.warn("Error while reporting subrepo config changes", e);
+        if (e instanceof VcsExtension)
+          throw (VcsException) e;
+        throw new VcsException(e);
+      }
+    }
+    return attributes;
+  }
+
+
+  private void fillSubrepoConfigChanges(@NotNull SubrepoConfigChangesAttributes builder,
+                                        @NotNull HgVcsRoot mainRoot,
+                                        @NotNull HgSubrepoConfigChange c) throws URISyntaxException, VcsException {
+    List<String> prevRevisions = new ArrayList<String>();
+    if (!(c.subrepoUrlChanged() || c.subrepoAdded() || c.subrepoRemoved())) {
+      String subrepoUrl = c.getCurrent().resolveUrl(mainRoot.getRepository());
+      String curRevision = c.getCurrent().revision();
+      for (SubRepo prevSubrepo : c.getPrevious()) {
+        prevRevisions.add(prevSubrepo.revision());
+      }
+      builder.addSubrepoConfigChange(new SubrepoConfigChange(mainRoot)
+              .setSubrepoPath(c.getPath())
+              .setSubrepoRootParamDiff(Constants.REPOSITORY_PROP, subrepoUrl)
+              .setCurrentSubrepoRevision(curRevision)
+              .setPreviousSubrepoRevisions(prevRevisions));
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialServerExtension.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,4 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+public interface MercurialServerExtension {
+}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Mon Mar 18 12:08:16 2013 +0400
@@ -15,11 +15,9 @@
  */
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
-import jetbrains.buildServer.BuildAgent;
 import jetbrains.buildServer.Used;
 import jetbrains.buildServer.buildTriggers.vcs.AbstractVcsPropertiesProcessor;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnknownRevisionException;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnrelatedRepositoryException;
 import jetbrains.buildServer.log.Loggers;
 import jetbrains.buildServer.serverSide.*;
@@ -28,7 +26,6 @@
 import jetbrains.buildServer.util.FileUtil;
 import jetbrains.buildServer.util.cache.ResetCacheRegister;
 import jetbrains.buildServer.vcs.*;
-import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import jetbrains.buildServer.vcs.patches.PatchBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -39,7 +36,7 @@
 import java.io.IOException;
 import java.util.*;
 
-import static java.util.Arrays.asList;
+import static java.util.Collections.emptyMap;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.HgFileUtil.deleteDir;
 
 /**
@@ -53,9 +50,7 @@
  * <p>Working copy of repository is created in the $TEAMCITY_DATA_PATH/system/caches/hg_&lt;hash code> folder.
  * <p>Personal builds (remote runs) are not yet supported, they require corresponding functionality from the IDE.
  */
-public class MercurialVcsSupport extends ServerVcsSupport implements LabelingSupport, VcsFileContentProvider, BranchSupport,
-        CollectChangesBetweenRoots, CollectChangesBetweenRepositories, BuildPatchByCheckoutRules {
-  private final VcsManager myVcsManager;
+public class MercurialVcsSupport extends ServerVcsSupport implements LabelingSupport, VcsFileContentProvider, BuildPatchByCheckoutRules {
   private final MirrorManager myMirrorManager;
   private final ServerPluginConfig myConfig;
   private final HgPathProvider myHgPathProvider;
@@ -64,10 +59,9 @@
   private final FileFilter myIgnoreDotHgFilter = new IgnoreDotHgFilter();
   private final FileFilter myAcceptAllFilter = new AcceptAllFilter();
   private final HgTestConnectionSupport myTestConnection;
+  private Collection<MercurialServerExtension> myExtensions;
 
-  public MercurialVcsSupport(@NotNull final VcsManager vcsManager,
-                             @NotNull final SBuildServer server,
-                             @NotNull final EventDispatcher<BuildServerListener> dispatcher,
+  public MercurialVcsSupport(@NotNull final EventDispatcher<ServerListener> dispatcher,
                              @NotNull final ResetCacheRegister resetCacheHandlerManager,
                              @NotNull final ServerPluginConfig config,
                              @NotNull final HgPathProvider hgPathProvider,
@@ -75,7 +69,6 @@
                              @NotNull final MirrorManager mirrorManager,
                              @NotNull final HgVcsRootFactory hgVcsRootFactory,
                              @NotNull final HgTestConnectionSupport testConnection) {
-    myVcsManager = vcsManager;
     myConfig = config;
     myMirrorManager = mirrorManager;
     myHgPathProvider = hgPathProvider;
@@ -83,30 +76,19 @@
     myHgVcsRootFactory = hgVcsRootFactory;
     myTestConnection = testConnection;
     resetCacheHandlerManager.registerHandler(new MercurialResetCacheHandler(myMirrorManager));
-    dispatcher.addListener(new BuildServerAdapter() {
-      @Override
-      public void cleanupFinished() {
-        server.getExecutor().submit(new Cleanup(myVcsManager, myMirrorManager, myConfig));
-      }
-
+    dispatcher.addListener(new ServerListenerAdapter() {
       @Override
       public void serverShutdown() {
         myRepoFactory.dispose();
       }
-
-      @Override
-      public void sourcesVersionReleased(@NotNull final BuildAgent agent) {
-        super.sourcesVersionReleased(agent);
-        server.getExecutor().submit(new Runnable() {
-          public void run() {
-            deleteWithLocking(myMirrorManager.getMirrors());
-          }
-        });
-      }
     });
     logUsedHg();
   }
 
+  public void setExtensions(@NotNull Collection<MercurialServerExtension> extensions) {
+    myExtensions = extensions;
+  }
+
   private void logUsedHg() {
     String hgPath = myConfig.getHgPath();
     if (hgPath != null)
@@ -115,50 +97,6 @@
       Loggers.VCS.info("Server-wide hg path is not set, will use path from the VCS root settings");
   }
 
-  private void deleteWithLocking(Collection<File> filesForDelete) {
-    for (File f : filesForDelete) {
-      lockWorkDir(f);
-      try {
-        FileUtil.delete(f);
-      } finally {
-        unlockWorkDir(f);
-      }
-    }
-  }
-
-  private List<VcsChange> toVcsChanges(final List<FileStatus> modifiedFiles, String prevVer, String curVer, CheckoutRules rules) {
-    List<VcsChange> files = new ArrayList<VcsChange>();
-    for (FileStatus mf: modifiedFiles) {
-      final String path = rules.map(mf.getPath());
-      if (shouldInclude(path))
-        files.add(toVcsChange(mf, prevVer, curVer, path));
-    }
-    return files;
-  }
-
-  private boolean shouldInclude(String path) {
-    return path != null;
-  }
-
-  private VcsChange toVcsChange(FileStatus mf, String prevVer, String curVer, String mappedPath) {
-    String normalizedPath = PathUtil.normalizeSeparator(mf.getPath());
-    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;
-    }
-    return new VcsChange(changeType, mf.getStatus().getName(), normalizedPath, mappedPath, prevVer, curVer);
-  }
-
-  private VcsChangeInfo.Type getChangeType(final 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(@NotNull final VcsModification vcsModification,
                            @NotNull final VcsChangeInfo change,
@@ -222,11 +160,11 @@
     HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
     syncRepository(hgRoot);
     HgRepo repo = createRepo(hgRoot);
-    Map<String, ChangeSet> result = repo.branches().call();
-    ChangeSet cset = result.get(hgRoot.getBranchName());
-    if (cset == null)
+    Map<String, String> result = repo.branches().call();
+    String revision = result.get(hgRoot.getBranchName());
+    if (revision == null)
       throw new VcsException("Unable to find current version for the branch: " + hgRoot.getBranchName());
-    return cset.getId();
+    return revision;
   }
 
   public boolean sourcesUpdatePossibleIfChangesNotFound(@NotNull final VcsRoot root) {
@@ -413,6 +351,7 @@
     try {
       if (repo.isValidRepository()) {
         try {
+          resetBookmarks(repo);
           repo.pull().fromRepository(root.getRepository())
                   .withTimeout(myConfig.getPullTimeout())
                   .call();
@@ -433,6 +372,15 @@
     }
   }
 
+
+  private void resetBookmarks(HgRepo repo) throws VcsException {
+    if (!myConfig.bookmarksEnabled())
+      return;
+    HgVersion v = repo.version().call();
+    if (v.isEqualsOrGreaterThan(BookmarksCommand.REQUIRED_HG_VERSION))
+      repo.resetBookmarks();
+  }
+
   @Override
   public LabelingSupport getLabelingSupport() {
     return this;
@@ -444,226 +392,41 @@
   }
 
   @NotNull
-  public String getRemoteRunOnBranchPattern() {
-    return "remote-run/*";
-  }
-
-  @NotNull
-  public RepositoryState getCurrentState(@NotNull VcsRoot root) throws VcsException {
+  public RepositoryStateData getCurrentState(@NotNull VcsRoot root) throws VcsException {
     HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
-    Map<String, String> branchRevisions = getBranchesRevisions(hgRoot);
+    syncRepository(hgRoot);
+    Map<String, String> revisions = new HashMap<String, String>();
+    revisions.putAll(getBookmarkRevisions(hgRoot));
+    revisions.putAll(getBranchesRevisions(hgRoot));
     String defaultBranchName = hgRoot.getBranchName();
-    if (branchRevisions.get(defaultBranchName) == null) {
-      VcsException e = new VcsException("Cannot find revision of the default branch '" +
+    if (revisions.get(defaultBranchName) == null) {
+      throw new VcsException("Cannot find revision of the default branch '" +
               defaultBranchName + "' of vcs root " + LogUtil.describe(root));
-      e.setRoot(root);
-      throw e;
     }
-    return RepositoryStateFactory.createRepositoryState(branchRevisions, defaultBranchName);
+    return RepositoryStateData.createVersionState(defaultBranchName, revisions);
   }
 
   @NotNull
   private Map<String, String> getBranchesRevisions(@NotNull HgVcsRoot root) throws VcsException {
-    syncRepository(root);
     HgRepo repo = createRepo(root);
-    Map<String, String> result = new HashMap<String, String>();
-    for (Map.Entry<String, ChangeSet> entry : repo.branches().call().entrySet()) {
-      result.put(entry.getKey(), entry.getValue().getId());
-    }
-    return result;
-  }
-
-  @NotNull
-  public Map<String, String> getBranchRootOptions(@NotNull VcsRoot root, @NotNull String branchName) {
-    final Map<String, String> options = new HashMap<String, String>(root.getProperties());
-    options.put(Constants.BRANCH_NAME_PROP, branchName);
-    return options;
-  }
-
-
-  @Nullable
-  public PersonalBranchDescription getPersonalBranchDescription(@NotNull VcsRoot root, @NotNull String branchName) throws VcsException {
-    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
-    VcsRoot branchRoot = createBranchRoot(root, branchName);
-    String baseVersion = getCurrentVersion(root);
-    String branchVersion = getCurrentVersion(branchRoot);
-    String mergeBase = getMergeBase(hgRoot, baseVersion, branchVersion);
-
-    if (mergeBase == null)
-      return null;
-
-    List<ChangeSet> changeSets = createRepo(hgRoot).log()
-            .fromRevision(mergeBase)
-            .toRevision(branchVersion)
-            .showCommitsFromAllBranches()
-            .call();
-    if (changeSets.size() > 1) {//when branch points to the commit in original branch we get 1 cset
-      String branchId = changeSets.get(1).getId();
-      String username = changeSets.get(changeSets.size() - 1).getUser();
-      return new PersonalBranchDescription(branchId, username);
-    } else {
-      return null;
-    }
-  }
-
-
-  private VcsRoot createBranchRoot(VcsRoot original, String branchName) {
-    VcsRootImpl result = new VcsRootImpl(original.getId(), original.getProperties());
-    result.addProperty(Constants.BRANCH_NAME_PROP, branchName);
-    return result;
-  }
-
-  @NotNull
-  public List<ModificationData> collectChanges(@NotNull VcsRoot fromRoot,
-                                               @NotNull RepositoryState fromState,
-                                               @NotNull VcsRoot toRoot,
-                                               @NotNull RepositoryState toState,
-                                               @NotNull CheckoutRules rules) throws VcsException {
-    return collectChanges(toRoot, fromState, toState, rules);
+    return repo.branches().call();
   }
 
   @NotNull
-  public List<ModificationData> collectChanges(@NotNull VcsRoot root,
-                                               @NotNull RepositoryState fromState,
-                                               @NotNull RepositoryState toState,
-                                               @NotNull CheckoutRules rules) throws VcsException {
-    Set<String> reportedCsetIds = new HashSet<String>();
-    List<ModificationData> changes = new ArrayList<ModificationData>();
-    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
-    OperationContext ctx = new OperationContext(this, myRepoFactory, myHgPathProvider, fromState, toState);
-    ctx.syncRepository(hgRoot);
-    for (Map.Entry<String, String> entry : toState.getBranchRevisions().entrySet()) {
-      String branch = entry.getKey();
-      String toRevision = entry.getValue();
-      String fromRevision = fromState.getBranchRevisions().get(branch);
-      if (fromRevision == null)
-        fromRevision = fromState.getBranchRevisions().get(fromState.getDefaultBranchName());
-      if (toRevision.equals(fromRevision))
-        continue;
-
-      Collection<String> fromRevisions = ctx.getFromRevisionsForBranch(hgRoot, fromRevision, toRevision);
-      List<ModificationData> branchChanges = collectChanges(hgRoot, fromRevisions, toRevision, rules);
-      for (ModificationData change : branchChanges) {
-        if (reportedCsetIds.add(change.getVersion()))
-          changes.add(change);
-      }
-    }
-    return changes;
-  }
-
-  @NotNull
-  public List<ModificationData> collectChanges(@NotNull VcsRoot fromRoot, @NotNull String fromRootRevision,
-                                               @NotNull VcsRoot toRoot, @Nullable String toRootRevision,
-                                               @NotNull CheckoutRules checkoutRules) throws VcsException {
-    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(toRoot);
-    syncRepository(hgRoot);
-    String toRevision = toRootRevision != null ? toRootRevision : getCurrentVersion(toRoot);
-    String mergeBase = getMergeBase(hgRoot, fromRootRevision, toRevision);
-    if (mergeBase == null)
-      return Collections.emptyList();
-    return collectChanges(hgRoot, asList(mergeBase), toRootRevision, checkoutRules);
-  }
-
-
-  @Nullable
-  private String getMergeBase(@NotNull HgVcsRoot root, @NotNull String revision1, @NotNull String revision2) throws VcsException {
-    String result = createRepo(root).mergeBase()
-            .revision1(revision1)
-            .revision2(revision2)
-            .call();
-    if (result == null)
-      result = getMinusNthCommit(root, 10);
-    return result;
-  }
-
-
-  @Nullable
-  private String getMinusNthCommit(@NotNull HgVcsRoot root, int n) throws VcsException {
-    LogCommand log = createRepo(root).log()
-            .inBranch(root.getBranchName())
-            .toNamedRevision(root.getBranchName());
-    if (n > 0)
-      log.setLimit(n);
-    List<ChangeSet> changeSets = log.call();
-    if (changeSets.isEmpty())
-      return null;
-    return changeSets.get(0).getId();
+  private Map<String, String> getBookmarkRevisions(@NotNull HgVcsRoot root) throws VcsException {
+    ServerHgRepo repo = createRepo(root);
+    if (!myConfig.bookmarksEnabled())
+      return emptyMap();
+    HgVersion v = repo.version().call();
+    if (!v.isEqualsOrGreaterThan(BookmarksCommand.REQUIRED_HG_VERSION))
+      return emptyMap();
+    return repo.bookmarks().call();
   }
 
 
   @NotNull
-  public CollectChangesPolicy getCollectChangesPolicy() {
-    return this;
-  }
-
-  public List<ModificationData> collectChanges(@NotNull VcsRoot root, @NotNull String fromVersion, @Nullable String currentVersion, @NotNull CheckoutRules checkoutRules) throws VcsException {
-    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
-    syncRepository(hgRoot);
-    return collectChanges(hgRoot, asList(fromVersion), currentVersion, checkoutRules);
-  }
-
-
-  private List<ModificationData> collectChanges(@NotNull HgVcsRoot root, @NotNull Collection<String> fromVersions, @Nullable String currentVersion, @NotNull CheckoutRules checkoutRules) throws VcsException {
-    List<ModificationData> result = new ArrayList<ModificationData>();
-    for (ChangeSet cset : getChangesets(root, fromVersions, currentVersion)) {
-      result.add(createModificationData(cset, root.getOriginalRoot(), checkoutRules));
-    }
-    return result;
-  }
-
-
-  private ModificationData createModificationData(@NotNull final ChangeSet cset, @NotNull final VcsRoot root, @NotNull final CheckoutRules checkoutRules) {
-    List<ChangeSetRevision> parents = cset.getParents();
-    if (parents.isEmpty())
-      throw new IllegalStateException("Commit " + cset.getId() + " has no parents");
-    List<VcsChange> files = toVcsChanges(cset.getModifiedFiles(), parents.get(0).getId(), cset.getId(), checkoutRules);
-    final ModificationData result = new ModificationData(cset.getTimestamp(), files, cset.getDescription(), cset.getUser(), root, cset.getId(), cset.getId());
-    for (ChangeSetRevision parent : parents) {
-      result.addParentRevision(parent.getId());
-    }
-    setCanBeIgnored(result, cset);
-    return result;
-  }
-
-
-  private void setCanBeIgnored(@NotNull ModificationData md, @NotNull ChangeSet cset) {
-    if (md.getParentRevisions().size() > 1) {
-      //don't ignore merge commits
-      md.setCanBeIgnored(false);
-    } else if (cset.getModifiedFiles().isEmpty()) {
-      //don't ignore empty commits
-      md.setCanBeIgnored(false);
-    }
-  }
-
-
-  @NotNull
-  private List<ChangeSet> getChangesets(@NotNull final HgVcsRoot root,
-                                        @NotNull final Collection<String> fromVersions,
-                                        @Nullable final String toVersion) throws VcsException {
-    if (toVersion == null)
-      return Collections.emptyList();
-    List<String> fromCommits = new ArrayList<String>();
-    for (String fromVersion : fromVersions) {
-      fromCommits.add(new ChangeSetRevision(fromVersion).getId());
-    }
-    String toCommit = new ChangeSetRevision(toVersion).getId();
-    try {
-      List<ChangeSet> changesets = createRepo(root).collectChanges(root)
-              .fromRevision(fromCommits)
-              .toRevision(toCommit)
-              .call();
-      Iterator<ChangeSet> iter = changesets.iterator();
-      while (iter.hasNext()) {
-        ChangeSet cset = iter.next();
-        if (fromVersions.contains(cset.getId()))
-          iter.remove();//skip already reported changes
-      }
-      return changesets;
-    } catch (UnknownRevisionException e) {
-      Loggers.VCS.warn("Revision '" + e.getRevision() + "' is unknown, will return no changes");
-      return Collections.emptyList();
-    }
+  public MercurialCollectChangesPolicy getCollectChangesPolicy() {
+    return new MercurialCollectChangesPolicy(this, myConfig, myHgVcsRootFactory, myRepoFactory, myHgPathProvider);
   }
 
 
@@ -786,25 +549,20 @@
     }
   }
 
-  ServerHgRepo createRepo(@NotNull HgVcsRoot root) throws VcsException {
+  public ServerHgRepo createRepo(@NotNull HgVcsRoot root) throws VcsException {
     return myRepoFactory.create(getWorkingDir(root), myHgPathProvider.getHgPath(root), root.getAuthSettings());
   }
 
+  public ServerHgRepo createRepo(@NotNull OperationContext ctx, @NotNull HgVcsRoot root) throws VcsException {
+    return ctx.createRepo(getWorkingDir(root), myHgPathProvider.getHgPath(root), root.getAuthSettings());
+  }
+
+
   private HgRepo createRepo(@NotNull HgVcsRoot root, @NotNull File customDir) throws VcsException {
     return myRepoFactory.create(customDir, myHgPathProvider.getHgPath(root), root.getAuthSettings());
   }
 
   @NotNull
-  public String getBranchName(@NotNull final VcsRoot root) {
-    try {
-      HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
-      return hgRoot.getBranchName();
-    } catch (VcsException e) {
-      return "default";
-    }
-  }
-
-  @NotNull
   @Override
   public Map<String, String> getCheckoutProperties(@NotNull VcsRoot root) {
     Map<String, String> rootProperties = root.getProperties();
@@ -818,4 +576,17 @@
   public ListFilesPolicy getListFilesPolicy() {
     return new ListFilesSupport(this, myHgVcsRootFactory);
   }
+
+
+  @Override
+  @Nullable
+  protected <T extends VcsExtension> T getVcsCustomExtension(@NotNull final Class<T> extensionClass) {
+    if (myExtensions == null)
+      return null;
+    for (MercurialServerExtension e : myExtensions) {
+      if (extensionClass.isInstance(e))
+        return extensionClass.cast(e);
+    }
+    return null;
+  }
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/OperationContext.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/OperationContext.java	Mon Mar 18 12:08:16 2013 +0400
@@ -4,7 +4,10 @@
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot;
 import jetbrains.buildServer.util.graph.*;
-import jetbrains.buildServer.vcs.*;
+import jetbrains.buildServer.vcs.ModificationData;
+import jetbrains.buildServer.vcs.RepositoryStateData;
+import jetbrains.buildServer.vcs.VcsException;
+import jetbrains.buildServer.vcs.VcsRoot;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -18,17 +21,21 @@
   private final MercurialVcsSupport myVcs;
   private final RepoFactory myRepoFactory;
   private final HgPathProvider myHgPathProvider;
-  private final RepositoryState myFromState;
-  private final RepositoryState myToState;
+  private final RepositoryStateData myFromState;
+  private final RepositoryStateData myToState;
   private final Map<VcsRootKey, DAG<String>> myDags = new HashMap<VcsRootKey, DAG<String>>();
   private Set<File> mySyncedDirs = new HashSet<File>();
+  private Map<String, HgVersion> myHgVersions = new HashMap<String, HgVersion>();
+  private Map<String, Set<SubrepoChangesInterval>> myProcessedSubrepoChanges = new HashMap<String, Set<SubrepoChangesInterval>>();//subrepo url -> processed changes intervals
+  private Map<VcsRootKey, Set<String>> myRevisionsPerRoot = new HashMap<VcsRootKey, Set<String>>();
   private Map<File, ServerHgRepo> myRepos = new HashMap<File, ServerHgRepo>();
+  private boolean myIncludeFromRevisions = false;//by default don't include them, they should be included only for subrepos
 
   public OperationContext(@NotNull MercurialVcsSupport vcs,
                           @NotNull RepoFactory repoFactory,
                           @NotNull HgPathProvider hgPathProvider,
-                          @NotNull RepositoryState fromState,
-                          @NotNull RepositoryState toState) {
+                          @NotNull RepositoryStateData fromState,
+                          @NotNull RepositoryStateData toState) {
     myVcs = vcs;
     myRepoFactory = repoFactory;
     myHgPathProvider = hgPathProvider;
@@ -36,6 +43,14 @@
     myToState = toState;
   }
 
+  public OperationContext(@NotNull MercurialVcsSupport vcs,
+                          @NotNull RepoFactory repoFactory,
+                          @NotNull HgPathProvider hgPathProvider,
+                          @NotNull String fromVersion,
+                          @NotNull String toVersion) {
+    this(vcs, repoFactory, hgPathProvider, RepositoryStateData.createSingleVersionState(fromVersion), RepositoryStateData.createSingleVersionState(toVersion));
+  }
+
   public void syncRepository(@NotNull final HgVcsRoot root) throws VcsException {
     File dir = myVcs.getWorkingDir(root);
     if (mySyncedDirs.contains(dir))
@@ -45,15 +60,77 @@
   }
 
   @NotNull
+  public HgVersion getHgVersion(@NotNull ServerHgRepo repo) throws VcsException {
+    String hgPath = repo.getHgPath();
+    HgVersion cachedVersion = myHgVersions.get(hgPath);
+    if (cachedVersion != null)
+      return cachedVersion;
+    HgVersion version = repo.version().call();
+    myHgVersions.put(hgPath, version);
+    return version;
+  }
+
+  public void markProcessedSubrepoChanges(@NotNull VcsRoot subrepo, @NotNull List<String> previousSubrepoRevisions, @NotNull String currentSubrepoRevision) {
+    String subrepoUrl = subrepo.getProperty(Constants.REPOSITORY_PROP);
+    Set<SubrepoChangesInterval> processedSubrepoChanges = myProcessedSubrepoChanges.get(subrepoUrl);
+    if (processedSubrepoChanges == null) {
+      processedSubrepoChanges = new HashSet<SubrepoChangesInterval>();
+      myProcessedSubrepoChanges.put(subrepoUrl, processedSubrepoChanges);
+    }
+    processedSubrepoChanges.add(new SubrepoChangesInterval(previousSubrepoRevisions, currentSubrepoRevision));
+  }
+
+  public boolean isProcessedSubrepoChanges(@NotNull VcsRoot subrepo, @NotNull List<String> previousSubrepoRevisions, @NotNull String currentSubrepoRevision) {
+    String subrepoUrl = subrepo.getProperty(Constants.REPOSITORY_PROP);
+    Set<SubrepoChangesInterval> processedSubrepoChanges = myProcessedSubrepoChanges.get(subrepoUrl);
+    if (processedSubrepoChanges == null)
+      return false;
+    return processedSubrepoChanges.contains(new SubrepoChangesInterval(previousSubrepoRevisions, currentSubrepoRevision));
+  }
+
+  @NotNull
   public ServerHgRepo createRepo(@NotNull File workingDir, @NotNull String hgPath, @NotNull AuthSettings authSettings) throws VcsException {
     ServerHgRepo repo = myRepos.get(workingDir);
     if (repo != null)
       return repo;
     repo = myRepoFactory.create(workingDir, hgPath, authSettings);
+    repo.setOperationContext(this);
     myRepos.put(workingDir, repo);
     return repo;
   }
 
+  public boolean isReportedModification(@NotNull ModificationData m) {
+    Set<String> revisions = getReportedRootRevisions(m);
+    return revisions.contains(m.getVersion());
+  }
+
+  public void markAsReported(@NotNull ModificationData m) {
+    Set<String> revisions = getReportedRootRevisions(m);
+    revisions.add(m.getVersion());
+  }
+
+  @NotNull
+  private Set<String> getReportedRootRevisions(@NotNull ModificationData m) {
+    VcsRootKey key = VcsRootKey.create(m.getVcsRoot());
+    Set<String> revisions = myRevisionsPerRoot.get(key);
+    if (revisions == null) {
+      revisions = new HashSet<String>();
+      myRevisionsPerRoot.put(key, revisions);
+    }
+    return revisions;
+  }
+
+
+  public boolean includeFromRevisions() {
+    return myIncludeFromRevisions;
+  }
+
+
+  public void setIncludeFromRevisions(boolean doInclude) {
+    myIncludeFromRevisions = doInclude;
+  }
+
+
   /**
    * Collecting changes is per branch, but we should take revisions of other branches
    * into account otherwise plugin can report redundant changes. Consider the following graph:
@@ -116,6 +193,11 @@
     return fromRevisions;
   }
 
+  private final static class SubrepoChangesInterval extends Pair<List<String>, String> {
+    private SubrepoChangesInterval(@NotNull List<String> prevRevisions, @NotNull String currentRevision) {
+      super(prevRevisions, currentRevision);
+    }
+  }
 
   private final static class VcsRootKey extends Pair<String, String> {
     private VcsRootKey(@NotNull String repositoryUrl, @Nullable String subrepoPath) {
@@ -123,11 +205,12 @@
     }
 
     private static VcsRootKey create(@NotNull VcsRoot root) {
-      return new VcsRootKey(root.getProperty(Constants.REPOSITORY_PROP), null);
+      return new VcsRootKey(root.getProperty(Constants.REPOSITORY_PROP), root.getProperty("teamcity.internal.subrepo.path"));
     }
   }
 
 
+
   private final static class FindIntervalVisitor extends BFSVisitorAdapter<String> {
 
     private final DAG<String> myDag;
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java	Mon Mar 18 12:08:16 2013 +0400
@@ -23,6 +23,7 @@
   private File myLogTemplate;
   private File myLogNoFilesTemplate;
   private File myDagTemplate;
+  private OperationContext myContext;
 
   public ServerHgRepo(@NotNull CommandSettingsFactory commandSettingsFactory,
                       @NotNull ServerPluginConfig config,
@@ -34,6 +35,10 @@
     myConfig = config;
   }
 
+  public void setOperationContext(@NotNull OperationContext context) {
+    myContext = context;
+  }
+
   public ServerHgRepo withLogTemplates(@NotNull File logTemplate,
                                        @NotNull File logNoFilesTemplate,
                                        @NotNull File dagTemplate) {
@@ -71,7 +76,14 @@
     }
   }
 
+  public boolean supportRevsets() throws VcsException {
+    HgVersion hgVersion = getHgVersion();
+    return hgVersion.isEqualsOrGreaterThan(REVSET_HG_VERSION);
+  }
+
   private HgVersion getHgVersion() throws VcsException {
+    if (myContext != null)
+      return myContext.getHgVersion(this);
     return version().call();
   }
 
@@ -82,11 +94,6 @@
     return myConfig.getRevsetParentRootIds().contains(parentId);
   }
 
-  public boolean supportRevsets() throws VcsException {
-    HgVersion hgVersion = getHgVersion();
-    return hgVersion.isEqualsOrGreaterThan(REVSET_HG_VERSION);
-  }
-
   @NotNull
   public DAG<String> loadDag() throws VcsException {
     LoadDagCommand loadDag = new LoadDagCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings, myDagTemplate);
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java	Mon Mar 18 12:08:16 2013 +0400
@@ -22,5 +22,9 @@
   @NotNull
   Set<Long> getRevsetParentRootIds();
 
-  int getMaxDagNodesCount();
+  public boolean detectSubrepoChanges();
+
+  public boolean bookmarksEnabled();
+
+  public int getMaxDagNodesCount();
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java	Mon Mar 18 12:08:16 2013 +0400
@@ -1,6 +1,7 @@
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
 import com.intellij.openapi.diagnostic.Logger;
+import jetbrains.buildServer.serverSide.CachePaths;
 import jetbrains.buildServer.serverSide.ServerPaths;
 import jetbrains.buildServer.serverSide.TeamCityProperties;
 import org.jetbrains.annotations.NotNull;
@@ -24,8 +25,8 @@
 
   private final File myCachesDir;
 
-  public ServerPluginConfigImpl(@NotNull final ServerPaths paths) {
-    myCachesDir = new File(paths.getCachesDir(), "mercurial");
+  public ServerPluginConfigImpl(@NotNull final CachePaths paths) {
+    myCachesDir = paths.getCacheDirectory("mercurial");
   }
 
   public boolean isUsePullProtocol() {
@@ -71,4 +72,12 @@
     }
     return ids;
   }
+
+  public boolean detectSubrepoChanges() {
+    return TeamCityProperties.getBooleanOrTrue("teamcity.hg.detectSubrepoChanges");
+  }
+
+  public boolean bookmarksEnabled() {
+    return TeamCityProperties.getBooleanOrTrue("teamcity.hg.enableBookmarks");
+  }
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesCommand.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesCommand.java	Mon Mar 18 12:08:16 2013 +0400
@@ -12,6 +12,7 @@
 
   protected List<String> myFromRevisions;
   protected String myToRevision;
+  protected boolean myIncludeFromRevision;
 
   @NotNull
   public abstract List<ChangeSet> call(@NotNull List<String> fromCommits, @NotNull String toCommit) throws VcsException;
@@ -28,5 +29,8 @@
     return this;
   }
 
-
+  public CollectChangesCommand includeFromRevision(boolean doInclude) {
+    myIncludeFromRevision = doInclude;
+    return this;
+  }
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesWithRevsets.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesWithRevsets.java	Mon Mar 18 12:08:16 2013 +0400
@@ -29,7 +29,11 @@
     for (String from : fromCommits) {
       revsets.append(" - ancestors(").append(from).append(")");
     }
-
+    if (myIncludeFromRevision) {
+      for (String from : fromCommits) {
+        revsets.append(" + ").append(from);
+      }
+    }
     return myRepo.log()
             .showCommitsFromAllBranches()
             .withRevsets(revsets.toString())
Binary file mercurial-tests/lib/testng-5.7-jdk15.jar has changed
Binary file mercurial-tests/lib/testng-6.8.jar has changed
--- a/mercurial-tests/mercurial-tests.iml	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/mercurial-tests.iml	Mon Mar 18 12:08:16 2013 +0400
@@ -18,6 +18,8 @@
     <orderEntry type="library" name="TeamCity-TestsAPI" level="project" />
     <orderEntry type="library" name="TeamCity-impl" level="project" />
     <orderEntry type="library" name="TeamCityAPI-agent" level="project" />
+    <orderEntry type="library" name="TeamCity Vcs Api" level="project" />
+    <orderEntry type="module" module-name="mercurial-server-tc" />
   </component>
 </module>
 
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -18,7 +18,6 @@
 import jetbrains.buildServer.agent.AgentRunningBuild;
 import jetbrains.buildServer.agent.BuildAgentConfiguration;
 import jetbrains.buildServer.agent.BuildProgressLogger;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettings;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory;
 import jetbrains.buildServer.util.FileUtil;
 import jetbrains.buildServer.util.TestFor;
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSubreposTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSubreposTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -7,7 +7,6 @@
 import jetbrains.buildServer.agent.BuildProgressLogger;
 import jetbrains.buildServer.agent.vcs.UpdateByIncludeRules2;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettings;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.ConnectionRefusedException;
 import jetbrains.buildServer.log.Log4jFactory;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BookmarksTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,180 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import com.intellij.openapi.diagnostic.Logger;
+import jetbrains.buildServer.TempFiles;
+import jetbrains.buildServer.log.Log4jFactory;
+import jetbrains.buildServer.vcs.RepositoryStateData;
+
+import jetbrains.buildServer.vcs.VcsRoot;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.*;
+
+import java.io.File;
+import java.io.IOException;
+
+import static com.intellij.openapi.util.io.FileUtil.delete;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.BookmarksTest.RepositoryStateDataMatcher.hasBranch;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.BookmarksTest.RepositoryStateDataMatcher.hasNoBranch;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.ServerPluginConfigBuilder.serverPluginConfig;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+
+@RequiredHgVersion(min = "2.4")
+@Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion")
+public class BookmarksTest {
+
+  static {
+    Logger.setFactory(new Log4jFactory());
+  }
+
+  private TempFiles myTempFiles;
+  private File myRemoteRepository;
+  private ServerPluginConfig myConfig;
+  private MercurialVcsSupport myVcs;
+  private VcsRoot myRoot;
+
+  @BeforeMethod
+  public void setUp() throws Exception {
+    myTempFiles = new TempFiles();
+    myRemoteRepository = myTempFiles.createTempDir();
+    myConfig = serverPluginConfig()
+            .cachesDir(myTempFiles.createTempDir())
+            .hgPath(Util.getHgPath())
+            .build();
+    myVcs = mercurialSupport().withConfig(myConfig).build();
+
+    myRoot = vcsRoot().withUrl(myRemoteRepository.getAbsolutePath()).build();
+  }
+
+  @AfterMethod
+  public void tearDown() {
+    myTempFiles.cleanup();
+  }
+
+
+  public void current_state_should_include_bookmarks(@NotNull HgVersion _) throws Exception {
+    setupRemoteRepositoryWithTwoBookmarks();
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark1").withRevision("15b4a116520d"));
+    assertThat(state, hasBranch("bookmark2").withRevision("e9f8f67888f5"));
+  }
+
+
+  public void remove_bookmark_when_it_is_removed_from_remote_repo(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    allBookmarksRemoved();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasNoBranch("bookmark1"));
+    assertThat(state, hasNoBranch("bookmark2"));
+  }
+
+
+  public void update_bookmark_when_it_is_updated_in_remote_repo(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    bookmark1Updated();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark1").withRevision("7597a4da7195"));
+  }
+
+
+  public void update_bookmark_when_it_is_deverged_in_remote_repo(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    bookmark1Diverged();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark1").withRevision("e9f8f67888f5"));
+  }
+
+
+  public void prefer_branch_to_bookmark_when_their_names_collide(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    branchWithNameBookmark2Created();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark2").withRevision("f63a14e873d6"));
+  }
+
+
+  private void setupRemoteRepositoryWithTwoBookmarks() throws IOException {
+    Util.copyRepository(new File("mercurial-tests/testData/bookmarks/1"), myRemoteRepository);
+  }
+
+  private void cloneRepositoryWithTwoBookmarks() throws Exception {
+    setupRemoteRepositoryWithTwoBookmarks();
+    myVcs.getCurrentState(myRoot);
+  }
+
+  private void bookmark1Updated() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/2");
+  }
+
+  private void allBookmarksRemoved() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/3");
+  }
+
+  private void bookmark1Diverged() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/4");
+  }
+
+  private void branchWithNameBookmark2Created() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/");
+    delete(myRemoteRepository);
+    Util.copyRepository(new File("mercurial-tests/testData/bookmarks/5"), myRemoteRepository);
+  }
+
+  private void updateRepository(@NotNull String path) throws IOException {
+    delete(myRemoteRepository);
+    Util.copyRepository(new File(path), myRemoteRepository);
+  }
+
+
+  static class RepositoryStateDataMatcher extends TypeSafeMatcher<RepositoryStateData> {
+
+    private String myBranch;
+    private String myRevision;
+
+    RepositoryStateDataMatcher(@NotNull String branch) {
+      myBranch = branch;
+    }
+
+    public static RepositoryStateDataMatcher hasBranch(@NotNull String branch) {
+      return new RepositoryStateDataMatcher(branch);
+    }
+
+    public static RepositoryStateDataMatcher hasNoBranch(@NotNull String branch) {
+      return new RepositoryStateDataMatcher(branch);
+    }
+
+    public RepositoryStateDataMatcher withRevision(@NotNull String revision) {
+      myRevision = revision;
+      return this;
+    }
+
+    @Override
+    public boolean matchesSafely(RepositoryStateData repositoryStateData) {
+      String actualRevision = repositoryStateData.getBranchRevisions().get(myBranch);
+      if (myRevision == null && actualRevision != null ||
+          myRevision != null && !myRevision.equals(actualRevision))
+        return false;
+      return true;
+    }
+
+    public void describeTo(Description description) {
+      if (myRevision == null) {
+        description.appendText("a repository state without branch ").appendValue(myBranch);
+      } else {
+        description.appendText("a repository state where branch ").appendValue(myBranch).appendText(" has revision ").appendValue(myRevision);
+      }
+    }
+  }
+}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/DagFeaturesTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/DagFeaturesTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -7,13 +7,13 @@
 import jetbrains.buildServer.vcs.CheckoutRules;
 import jetbrains.buildServer.vcs.ModificationData;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
-import org.jmock.Mockery;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import java.io.File;
 import java.util.List;
 
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
@@ -37,7 +37,7 @@
     ServerPluginConfig config = new ServerPluginConfigBuilder()
             .cachesDir(myTempFiles.createTempDir())
             .build();
-    myHg = Util.createMercurialServerSupport(new Mockery(), config);
+    myHg = mercurialSupport().withConfig(config).build();
 
     File original = new File("mercurial-tests/testData/rep2");
     File copy = new File(myTempFiles.createTempDir(), "rep2");
@@ -54,13 +54,13 @@
   public void should_detect_changes_from_named_branches() throws Exception {
     VcsRootImpl root = new VcsRootBuilder().withUrl(myRepository).build();
 
-    List<ModificationData> changes = myHg.collectChanges(root, "8:b6e2d176fe8e", "12:1e620196c4b6", CheckoutRules.DEFAULT);
+    List<ModificationData> changes = myHg.getCollectChangesPolicy().collectChanges(root, "8:b6e2d176fe8e", "12:1e620196c4b6", CheckoutRules.DEFAULT);
     assertEquals(4, changes.size());
     for (ModificationData change : changes) {
       assertFalse(change.getParentRevisions().isEmpty());
     }
 
-    changes = myHg.collectChanges(root, "12:1e620196c4b6", "18:df04faa7575a", CheckoutRules.DEFAULT);
+    changes = myHg.getCollectChangesPolicy().collectChanges(root, "12:1e620196c4b6", "18:df04faa7575a", CheckoutRules.DEFAULT);
     assertEquals(6, changes.size());
     for (ModificationData change : changes) {
       assertFalse(change.getParentRevisions().isEmpty());
@@ -71,7 +71,7 @@
   @TestFor(issues = "TW-17882")
   public void should_report_changes_only_from_merged_named_branches() throws Exception {
     VcsRootImpl root = new VcsRootBuilder().withUrl(myRepository).build();
-    List<ModificationData> changes = myHg.collectChanges(root, "1e620196c4b6", "505c5b9d01e6", CheckoutRules.DEFAULT);
+    List<ModificationData> changes = myHg.getCollectChangesPolicy().collectChanges(root, "1e620196c4b6", "505c5b9d01e6", CheckoutRules.DEFAULT);
     assertEquals(2, changes.size());
   }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepoTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,65 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import com.intellij.openapi.diagnostic.Logger;
+import jetbrains.buildServer.TempFiles;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.AuthSettings;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory;
+import jetbrains.buildServer.log.Log4jFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.assertTrue;
+
+@Test
+public class HgRepoTest {
+
+  static {
+    Logger.setFactory(new Log4jFactory());
+  }
+
+  private TempFiles myTempFiles;
+
+  @BeforeMethod
+  public void setUp() throws IOException {
+    myTempFiles = new TempFiles();
+  }
+
+  @AfterMethod
+  public void tearDown() {
+    myTempFiles.cleanup();
+  }
+
+  public void subrepos() throws Exception {
+    File repository = myTempFiles.createTempDir();
+    copyRepository(new File("mercurial-tests/testData/subrepos/r1"), repository);
+    HgRepo repo = new HgRepo(new TestCommandSettingsFactory(), repository, Util.getHgPath(), new AuthSettings());
+    List<HgSubrepoConfigChange> changes = repo.getSubrepoConfigChanges("09c256b6163e");
+    assertEquals(1, changes.size());
+    HgSubrepoConfigChange c = changes.get(0);
+    assertEquals("r2", c.getPath());
+    //noinspection ConstantConditions
+    assertTrue(c.getPrevious().get(0).revision().startsWith("9e4a2fef1a1c"));
+    //noinspection ConstantConditions
+    assertTrue(c.getCurrent().revision().startsWith("ebb884b1b691"));
+
+    changes = repo.getSubrepoConfigChanges("4d7b3db8779f");
+    assertEquals(1, changes.size());
+    c = changes.get(0);
+    assertEquals("r2", c.getPath());
+    //noinspection ConstantConditions
+    assertTrue(c.getPrevious().get(0).revision().startsWith("916933c1dd8e"));
+    assertNull(c.getCurrent());
+
+    changes = repo.getSubrepoConfigChanges("d350e7209906");
+    assertEquals(1, changes.size());
+  }
+
+}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ListFilesSupportTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ListFilesSupportTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -9,7 +9,6 @@
 import jetbrains.buildServer.vcs.VcsFileData;
 import jetbrains.buildServer.vcs.VcsRoot;
 import org.jetbrains.annotations.NotNull;
-import org.jmock.Mockery;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -17,6 +16,7 @@
 import java.io.IOException;
 import java.util.Collection;
 
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
 import static org.testng.AssertJUnit.assertFalse;
@@ -40,11 +40,10 @@
   @BeforeMethod
   protected void setUp() throws Exception {
     TempFiles tempFiles = new TempFiles();
-    Mockery context = new Mockery();
     ServerPluginConfig myPluginConfig = new ServerPluginConfigBuilder()
             .cachesDir(tempFiles.createTempDir())
             .build();
-    myVcs = Util.createMercurialServerSupport(context, myPluginConfig);
+    myVcs = mercurialSupport().withConfig(myPluginConfig).build();
 
     myRemoteRepoDir = tempFiles.createTempDir();
     copyRepository(new File("mercurial-tests/testData/rep1"), myRemoteRepoDir);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,68 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsFactory;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory;
+import jetbrains.buildServer.serverSide.BuildServerListener;
+import jetbrains.buildServer.serverSide.SBuildServer;
+import jetbrains.buildServer.serverSide.ServerListener;
+import jetbrains.buildServer.util.EventDispatcher;
+import jetbrains.buildServer.util.cache.ResetCacheHandler;
+import jetbrains.buildServer.util.cache.ResetCacheRegister;
+import jetbrains.buildServer.vcs.VcsManager;
+import org.jetbrains.annotations.NotNull;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+public class MercurialSupportBuilder {
+
+  private Mockery myContext;
+  private ServerPluginConfig myConfig;
+  private List<MercurialServerExtension> myExtensions = new ArrayList<MercurialServerExtension>();
+  private HgVcsRootFactory myHgRootFactory;
+  private CommandSettingsFactory myCommandSettingsFactory = new TestCommandSettingsFactory();
+
+  public static MercurialSupportBuilder mercurialSupport() {
+    return new MercurialSupportBuilder();
+  }
+
+  @NotNull
+  public MercurialVcsSupport build() throws IOException {
+    if (myContext == null)
+      myContext = new Mockery();
+    EventDispatcher<ServerListener> dispatcher = EventDispatcher.create(ServerListener.class);
+    myHgRootFactory = new HgVcsRootFactory(myConfig);
+    MirrorManagerImpl mirrorManager = new MirrorManagerImpl(myConfig);
+    ServerHgPathProvider hgPathProvider = new ServerHgPathProvider(myConfig);
+    RepoFactory repoFactory = new RepoFactory(myConfig, myCommandSettingsFactory);
+    HgTestConnectionSupport testConnection = new HgTestConnectionSupport(myHgRootFactory, repoFactory, mirrorManager, hgPathProvider);
+    final ResetCacheRegister resetCacheManager = myContext.mock(ResetCacheRegister.class);
+    myContext.checking(new Expectations() {{
+      allowing(resetCacheManager).registerHandler(with(any(ResetCacheHandler.class)));
+    }});
+    MercurialVcsSupport vcs = new MercurialVcsSupport(dispatcher, resetCacheManager, myConfig, hgPathProvider,
+            repoFactory, mirrorManager, myHgRootFactory, testConnection);
+    vcs.setExtensions(myExtensions);
+    return vcs;
+  }
+
+
+  public MercurialSupportBuilder withConfig(@NotNull ServerPluginConfig config) {
+    myConfig = config;
+    return this;
+  }
+
+  public MercurialSupportBuilder withExtension(@NotNull MercurialServerExtension extension) {
+    myExtensions.add(extension);
+    return this;
+  }
+
+  public HgVcsRootFactory getHgRootFactory() {
+    return myHgRootFactory;
+  }
+}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -20,10 +20,7 @@
 import jetbrains.buildServer.vcs.*;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import junit.framework.Assert;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
 import org.jetbrains.annotations.NotNull;
-import org.jmock.Mockery;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -34,13 +31,12 @@
 import java.util.*;
 
 import static com.intellij.openapi.util.io.FileUtil.*;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.ModificationDataMatcher.modificationData;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.buildPatch;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
 import static jetbrains.buildServer.util.Util.map;
-import static jetbrains.buildServer.vcs.RepositoryStateFactory.createRepositoryState;
-import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.hasItem;
 import static org.hamcrest.Matchers.not;
@@ -55,11 +51,10 @@
   @BeforeMethod
   protected void setUp() throws Exception {
     super.setUp();
-    Mockery context = new Mockery();
     myPluginConfig = new ServerPluginConfigBuilder()
             .cachesDir(myTempFiles.createTempDir())
             .build();
-    myVcs = Util.createMercurialServerSupport(context, myPluginConfig);
+    myVcs = mercurialSupport().withConfig(myPluginConfig).build();
   }
 
   protected String getTestDataPath() {
@@ -78,20 +73,20 @@
   }
 
   private List<ModificationData> collectChanges(@NotNull VcsRoot vcsRoot, @NotNull String from, @NotNull String to, @NotNull CheckoutRules rules) throws VcsException {
-    return myVcs.collectChanges(vcsRoot, from, to, rules);
+    return myVcs.getCollectChangesPolicy().collectChanges(vcsRoot, from, to, rules);
   }
 
   public void test_collect_changes_between_two_same_roots() throws Exception {
     VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
     VcsRootImpl sameVcsRoot = createVcsRoot(simpleRepo());
-    List<ModificationData> changes = myVcs.collectChanges(vcsRoot, "0:9875b412a788", sameVcsRoot, "3:9522278aa38d", new CheckoutRules(""));
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(vcsRoot, "0:9875b412a788", sameVcsRoot, "3:9522278aa38d", new CheckoutRules(""));
     do_check_for_collect_changes(changes);
   }
 
   public void test_collect_changes_from_non_existing_revision() throws Exception {
     VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
     VcsRootImpl sameVcsRoot = createVcsRoot(simpleRepo());
-    List<ModificationData> changes = myVcs.collectChanges(vcsRoot, "0:9875b412a789", sameVcsRoot, "3:9522278aa38d", new CheckoutRules(""));
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(vcsRoot, "0:9875b412a789", sameVcsRoot, "3:9522278aa38d", new CheckoutRules(""));
     assertFalse(changes.isEmpty());//should return some changes from the toRoot
   }
 
@@ -289,7 +284,7 @@
   @TestFor(issues = "TW-10076")
   public void should_allow_to_ignore_changes_where_all_files_excluded() throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root, "43023ea3f13b", "a2672ee13212", new CheckoutRules("-:.hgtags"));
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "43023ea3f13b", "a2672ee13212", new CheckoutRules("-:.hgtags"));
     assertEquals(changes.size(), 1);
     assertTrue(changes.get(0).isCanBeIgnored());
   }
@@ -298,7 +293,7 @@
   @TestFor(issues = "TW-10076")
   public void should_not_allow_to_ignore_close_branch_commits() throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root, "df04faa7575a", "43023ea3f13b", CheckoutRules.DEFAULT);
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "df04faa7575a", "43023ea3f13b", CheckoutRules.DEFAULT);
     assertEquals(changes.size(), 2);
     assertEquals(changes.get(1).getChangeCount(), 0);
     assertFalse(changes.get(1).isCanBeIgnored());
@@ -313,7 +308,7 @@
     myVcs.label("tag_by_specified_user", "10:9c6a6b4aede0", root, CheckoutRules.DEFAULT);
 
     String currentVersion = myVcs.getCurrentVersion(root);
-    List<ModificationData> changes = myVcs.collectChanges(root, "10:9c6a6b4aede0", currentVersion, CheckoutRules.DEFAULT);
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "10:9c6a6b4aede0", currentVersion, CheckoutRules.DEFAULT);
     assertEquals(changes.size(), 1);
     assertEquals(changes.get(0).getUserName(), customUserForTag);
   }
@@ -445,7 +440,7 @@
   public void test_collect_changes_between_two_different_roots() throws Exception {
     VcsRootImpl defaultRoot = createVcsRoot(mergeCommittsRepo());
     VcsRootImpl branchRoot = createVcsRoot(mergeCommittsRepo(), "test");
-    List<ModificationData> changes = myVcs.collectChanges(defaultRoot, "11:48177654181c", branchRoot, "10:fc524efc2bc4", CheckoutRules.DEFAULT);
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(defaultRoot, "11:48177654181c", branchRoot, "10:fc524efc2bc4", CheckoutRules.DEFAULT);
     assertEquals(changes.size(), 2);
 
     assertEquals(changes.get(0).getVersion(), "8c44244d6645");
@@ -455,7 +450,7 @@
   public void collectChanges_should_return_all_changes_from_branch() throws Exception {
     VcsRootImpl defaultBranchRoot = createVcsRoot(myRep2Path, "default");
     VcsRootImpl personalBranchRoot = createVcsRoot(myRep2Path, "personal-branch");
-    List<ModificationData> modifications = myVcs.collectChanges(defaultBranchRoot, "16:505c5b9d01e6", personalBranchRoot, "17:9ec402c74298", CheckoutRules.DEFAULT);
+    List<ModificationData> modifications = myVcs.getCollectChangesPolicy().collectChanges(defaultBranchRoot, "16:505c5b9d01e6", personalBranchRoot, "17:9ec402c74298", CheckoutRules.DEFAULT);
     assertEquals(3, modifications.size());
   }
 
@@ -533,22 +528,6 @@
   }
 
 
-  public void test_getPersonalBranchDescription_when_branch_contains_commits() throws Exception {
-    VcsRootImpl originalRoot = createVcsRoot(simpleRepo());
-    PersonalBranchDescription description = myVcs.getPersonalBranchDescription(originalRoot, "name with space");
-    assertNotNull(description);
-    assertEquals(description.getBranchId(), "376dcf05cd2a");
-    assertEquals(description.getUsername(), "Pavel.Sher");
-  }
-
-
-  public void test_getPersonalBranchDescription_when_branch_doesnot_contain_commits() throws Exception {
-    VcsRootImpl originalRoot = createVcsRoot(simpleRepo());
-    PersonalBranchDescription description = myVcs.getPersonalBranchDescription(originalRoot, "default");
-    assertNull(description);
-  }
-
-
   public void labeling_should_not_change_vcs_root_settings() throws Exception {
     VcsRootImpl root = createVcsRoot(simpleRepo(), "test_branch");
     assertNull(root.getProperty(Constants.SERVER_CLONE_PATH_PROP));
@@ -581,59 +560,35 @@
     assertEquals(russianLocaleVersion, defaultLocaleVersion);
   }
 
-
   public void collect_changes_between_states() throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root,
-            createRepositoryState(map("default", "1e620196c4b6"), "default"),
-            createRepositoryState(map("default", "505c5b9d01e6", "personal-branch", "96b78d73081d"), "default"),
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root,
+            RepositoryStateData.createVersionState("default", map("default", "1e620196c4b6")),
+            RepositoryStateData.createVersionState("default", map("default", "505c5b9d01e6", "personal-branch", "96b78d73081d")),
             CheckoutRules.DEFAULT);
     assertEquals(changes.size(), 4);
-    assertThat(changes, hasItem(withVersion("dec47d2d49bf")));
-    assertThat(changes, hasItem(withVersion("78e67807f916")));
-    assertThat(changes, hasItem(withVersion("96b78d73081d")));
-    assertThat(changes, hasItem(withVersion("505c5b9d01e6")));
+    assertThat(changes, hasItem(modificationData().withVersion("dec47d2d49bf")));
+    assertThat(changes, hasItem(modificationData().withVersion("78e67807f916")));
+    assertThat(changes, hasItem(modificationData().withVersion("96b78d73081d")));
+    assertThat(changes, hasItem(modificationData().withVersion("505c5b9d01e6")));
   }
 
 
   public void collect_changes_between_states_does_not_report_duplicate_changes() throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root,
-            createRepositoryState(map("default", "8c44244d6645"), "default"),
-            createRepositoryState(map("default", "505c5b9d01e6", "personal-branch", "9ec402c74298"), "default"),
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root,
+            RepositoryStateData.createVersionState("default", map("default", "8c44244d6645")),
+            RepositoryStateData.createVersionState("default", map("default", "505c5b9d01e6", "personal-branch", "9ec402c74298")),
             CheckoutRules.DEFAULT);
     assertEquals(changes.size(), 8);
-    assertThat(changes, hasItem(withVersion("9ec402c74298")));
-    assertThat(changes, hasItem(withVersion("505c5b9d01e6")));
-    assertThat(changes, hasItem(withVersion("96b78d73081d")));
-    assertThat(changes, hasItem(withVersion("78e67807f916")));
-    assertThat(changes, hasItem(withVersion("dec47d2d49bf")));
-    assertThat(changes, hasItem(withVersion("1e620196c4b6")));
-    assertThat(changes, hasItem(withVersion("48177654181c")));
-    assertThat(changes, hasItem(withVersion("fc524efc2bc4")));
-  }
-
-
-  private ModificationDataVersionMatcher withVersion(@NotNull String version) {
-    return new ModificationDataVersionMatcher(version);
-  }
-
-  class ModificationDataVersionMatcher extends TypeSafeMatcher<ModificationData> {
-
-    private final String myVersion;
-
-    public ModificationDataVersionMatcher(@NotNull String version) {
-      myVersion = version;
-    }
-
-    @Override
-    public boolean matchesSafely(ModificationData m) {
-      return myVersion.equals(m.getVersion());
-    }
-
-    public void describeTo(Description description) {
-      description.appendText("modification with version").appendValue(myVersion);
-    }
+    assertThat(changes, hasItem(modificationData().withVersion("9ec402c74298")));
+    assertThat(changes, hasItem(modificationData().withVersion("505c5b9d01e6")));
+    assertThat(changes, hasItem(modificationData().withVersion("96b78d73081d")));
+    assertThat(changes, hasItem(modificationData().withVersion("78e67807f916")));
+    assertThat(changes, hasItem(modificationData().withVersion("dec47d2d49bf")));
+    assertThat(changes, hasItem(modificationData().withVersion("1e620196c4b6")));
+    assertThat(changes, hasItem(modificationData().withVersion("48177654181c")));
+    assertThat(changes, hasItem(modificationData().withVersion("fc524efc2bc4")));
   }
 
 
@@ -641,9 +596,9 @@
   @Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion")
   public void should_not_report_redundant_changes_after_merge(@NotNull HgVersion _) throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root,
-            createRepositoryState(map("default", "505c5b9d01e6", "personal-branch", "9ec402c74298"), "default"),
-            createRepositoryState(map("default", "df04faa7575a", "personal-branch", "9ec402c74298"), "default"),
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root,
+            RepositoryStateData.createVersionState("default", map("default", "505c5b9d01e6", "personal-branch", "9ec402c74298")),
+            RepositoryStateData.createVersionState("default", map("default", "df04faa7575a", "personal-branch", "9ec402c74298")),
             CheckoutRules.DEFAULT);
     assertEquals(changes.size(), 1);
   }
@@ -653,9 +608,9 @@
   @Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion")
   public void should_not_report_duplicate_changes(@NotNull HgVersion _) throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root,
-            createRepositoryState(map("default", "505c5b9d01e6", "personal-branch", "96b78d73081d"), "default"),
-            createRepositoryState(map("default", "df04faa7575a", "personal-branch", "9ec402c74298"), "default"),
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root,
+            RepositoryStateData.createVersionState("default", map("default", "505c5b9d01e6", "personal-branch", "96b78d73081d")),
+            RepositoryStateData.createVersionState("default", map("default", "df04faa7575a", "personal-branch", "9ec402c74298")),
             CheckoutRules.DEFAULT);
     assertThat(changes, not(hasItem(modificationData().withVersion("dec47d2d49bf"))));
   }
@@ -665,12 +620,11 @@
   @Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion")
   public void should_not_report_duplicate_changes2(@NotNull HgVersion _) throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root,
-            createRepositoryState(map("default", "528572bbf77b", "personal-branch", "27184c50d7ef"), "default"),
-            createRepositoryState(map("default", "4780519e01aa", "personal-branch", "fd50e4842211"), "default"),
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root,
+            RepositoryStateData.createVersionState("default", map("default", "528572bbf77b", "personal-branch", "27184c50d7ef")),
+            RepositoryStateData.createVersionState("default", map("default", "4780519e01aa", "personal-branch", "fd50e4842211")),
             CheckoutRules.DEFAULT);
     assertThat(changes, not(hasItem(modificationData().withVersion("4dbb87c381be"))));
-    assertThat(changes.size(), is(4));
   }
 
 
@@ -678,13 +632,14 @@
   @Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion")
   public void should_not_report_all_changes_in_repository_if_default_branch_is_unrelated(@NotNull HgVersion _) throws Exception {
     VcsRootImpl root = createVcsRoot(myRep2Path);
-    List<ModificationData> changes = myVcs.collectChanges(root,
-            createRepositoryState(map("NULL", "1f355761350e"), "NULL"),
-            createRepositoryState(map("NULL", "1f355761350e", "personal-branch", "fd50e4842211"), "NULL"),
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root,
+            RepositoryStateData.createVersionState("NULL", map("NULL", "1f355761350e")),
+            RepositoryStateData.createVersionState("NULL", map("NULL", "1f355761350e", "personal-branch", "fd50e4842211")),
             CheckoutRules.DEFAULT);
     assertEquals(0, changes.size());
   }
 
+
   private void assertFiles(final List<String> expectedFiles, final ModificationData modificationData) {
     Set<String> actualFiles = new HashSet<String>();
     for (VcsChange vc: modificationData.getChanges()) {
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ModificationDataMatcher.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ModificationDataMatcher.java	Mon Mar 18 12:08:16 2013 +0400
@@ -5,14 +5,22 @@
 import org.hamcrest.TypeSafeMatcher;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import static jetbrains.buildServer.util.Util.map;
+
 public class ModificationDataMatcher extends TypeSafeMatcher<ModificationData> {
 
   private String myVersion;
+  private Map<String, String> myVcsRootProperties = new HashMap<String, String>();
 
   @Override
   public boolean matchesSafely(ModificationData m) {
     if (myVersion != null && !myVersion.equals(m.getDisplayVersion()))
       return false;
+    if (!myVcsRootProperties.isEmpty() && !myVcsRootProperties.equals(m.getVcsRootObject().getProperties()))
+      return false;
     return true;
   }
 
@@ -20,6 +28,8 @@
     description.appendText("modification");
     if (myVersion != null)
       description.appendText(" with version ").appendValue(myVersion);
+    if (!myVcsRootProperties.isEmpty())
+      description.appendText(" with vcs root properties ").appendValue(myVcsRootProperties);
   }
 
   public static ModificationDataMatcher modificationData() {
@@ -30,4 +40,9 @@
     myVersion = version;
     return this;
   }
+
+  public ModificationDataMatcher withVcsRootProperties(Map<String, String> properties) {
+    myVcsRootProperties.putAll(properties);
+    return this;
+  }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RevisionFormatTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RevisionFormatTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -8,7 +8,6 @@
 import jetbrains.buildServer.vcs.*;
 import jetbrains.buildServer.vcs.patches.PatchTestCase;
 import org.jetbrains.annotations.NotNull;
-import org.jmock.Mockery;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -19,6 +18,7 @@
 import java.util.List;
 import java.util.Map;
 
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.buildPatch;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
@@ -38,11 +38,10 @@
   @BeforeMethod
   public void setUp() throws Exception {
     myTempFiles = new TempFiles();
-    Mockery context = new Mockery();
-    ServerPluginConfig myPluginConfig = new ServerPluginConfigBuilder()
+    ServerPluginConfig pluginConfig = new ServerPluginConfigBuilder()
             .cachesDir(myTempFiles.createTempDir())
             .build();
-    myVcs = Util.createMercurialServerSupport(context, myPluginConfig);
+    myVcs = mercurialSupport().withConfig(pluginConfig).build();
 
     myRemoteRepoDir = copyRepository(myTempFiles, new File("mercurial-tests/testData/rep1").getAbsolutePath());
     myRoot = vcsRoot().withUrl(myRemoteRepoDir.getAbsolutePath()).build();
@@ -55,9 +54,9 @@
 
 
   public void collect_changes_result_does_not_depend_on_revnums() throws VcsException {
-    List<ModificationData> changesWithRevnums = myVcs.collectChanges(myRoot,
+    List<ModificationData> changesWithRevnums = myVcs.getCollectChangesPolicy().collectChanges(myRoot,
             "1:1d446e82d356", "3:9522278aa38d", CheckoutRules.DEFAULT);
-    List<ModificationData> changesWithoutRevnums = myVcs.collectChanges(myRoot,
+    List<ModificationData> changesWithoutRevnums = myVcs.getCollectChangesPolicy().collectChanges(myRoot,
             "1d446e82d356", "9522278aa38d", CheckoutRules.DEFAULT);
     assertEquals(changesWithoutRevnums, changesWithRevnums);
   }
@@ -108,7 +107,7 @@
 
 
   public void should_not_include_revnum_in_current_state() throws VcsException {
-    RepositoryState state = myVcs.getCurrentState(myRoot);
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
     for (Map.Entry<String, String> entry : state.getBranchRevisions().entrySet()) {
       String branchName = entry.getKey();
       String revision = entry.getKey();
@@ -118,7 +117,7 @@
 
 
   public void should_not_include_revnum_in_collected_changes() throws VcsException {
-    List<ModificationData> changes = myVcs.collectChanges(myRoot, "1d446e82d356", "9522278aa38d", CheckoutRules.DEFAULT);
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(myRoot, "1d446e82d356", "9522278aa38d", CheckoutRules.DEFAULT);
     for (ModificationData c : changes) {
       assertFalse(c.getVersion().contains(":"), "Change version contains revnum: " + c.toString());
       for (String parentVersion : c.getParentRevisions()) {
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -46,7 +46,7 @@
 
 
   private HgVcsRoot createHgRoot() throws Exception {
-    return new HgVcsRoot(new VcsRootBuilder().withHgPath(myVcsRootHgPath).build());
+    return new HgVcsRoot(new VcsRootBuilder().withUrl("some url").withHgPath(myVcsRootHgPath).build());
   }
 
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java	Mon Mar 18 12:08:16 2013 +0400
@@ -15,6 +15,7 @@
   private String myHgPath;
   private File myCachesDir;
   private boolean myDontUseRevsets = false;
+  private boolean myDetectSubrepoChanges = false;
 
   @NotNull
   public ServerPluginConfig build() {
@@ -48,6 +49,14 @@
         return new HashSet<Long>();
       }
 
+      public boolean detectSubrepoChanges() {
+        return myDetectSubrepoChanges;
+      }
+
+      public boolean bookmarksEnabled() {
+        return true;
+      }
+
       public int getMaxDagNodesCount() {
         return 0;
       }
@@ -59,7 +68,6 @@
     return new ServerPluginConfigBuilder();
   }
 
-
   public ServerPluginConfigBuilder userPullProtocol(boolean doUse) {
     myUsePullProtocol = doUse;
     return this;
@@ -79,4 +87,9 @@
     myDontUseRevsets = true;
     return this;
   }
+
+  public ServerPluginConfigBuilder detectSubrepoChanges(boolean doDetect) {
+    myDetectSubrepoChanges = doDetect;
+    return this;
+  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubrepoChangesTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,168 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import com.intellij.openapi.diagnostic.Logger;
+import jetbrains.buildServer.TempFiles;
+import jetbrains.buildServer.log.Log4jFactory;
+import jetbrains.buildServer.vcs.*;
+import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static java.util.Arrays.asList;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.ModificationDataMatcher.modificationData;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.testng.AssertJUnit.assertEquals;
+
+@RequiredHgVersion(min = "1.7.0") //support subrepos only for hg with revsets
+@Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion")
+public class SubrepoChangesTest {
+
+  static {
+    Logger.setFactory(new Log4jFactory());
+  }
+
+  private TempFiles myTempFiles;
+  private MercurialVcsSupport myVcs;
+  private File myRemoteRepo1;
+  private File myRemoteRepo2;
+  private File myRemoteRepo3;
+
+  @BeforeMethod
+  public void setUp() throws IOException {
+    myTempFiles = new TempFiles();
+    ServerPluginConfig pluginConfig = new ServerPluginConfigBuilder()
+            .cachesDir(myTempFiles.createTempDir())
+            .detectSubrepoChanges(true)
+            .build();
+    File remoteRepoParentDir = myTempFiles.createTempDir();
+    myRemoteRepo1 = new File(remoteRepoParentDir, "r1");
+    myRemoteRepo2 = new File(remoteRepoParentDir, "r2");
+    myRemoteRepo3 = new File(remoteRepoParentDir, "r3");
+    copyRepository(new File("mercurial-tests/testData/subrepos/r1"), myRemoteRepo1);
+    copyRepository(new File("mercurial-tests/testData/subrepos/r2"), myRemoteRepo2);
+    copyRepository(new File("mercurial-tests/testData/subrepos/r3"), myRemoteRepo3);
+    myVcs = mercurialSupport().withConfig(pluginConfig).build();
+  }
+
+  @AfterMethod
+  public void tearDown() {
+    myTempFiles.cleanup();
+  }
+
+
+  public void should_report_changes_from_subrepos(@NotNull HgVersion _) throws Exception {
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "d350e7209906", "09c256b6163e", CheckoutRules.DEFAULT);
+    assertEquals(4, changes.size());
+  }
+
+
+  public void should_include_from_revisions_into_changes_from_subrepos(@NotNull HgVersion _) throws Exception {
+    //otherwise TeamCity won't show changes from subrepos in UI
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "d350e7209906", "09c256b6163e", CheckoutRules.DEFAULT);
+    assertThat(changes, hasItem(modificationData().withVersion("9e4a2fef1a1c")));
+  }
+
+
+  public void should_not_report_any_changes_when_subrepo_removed(@NotNull HgVersion _) throws Exception {
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "34017377d9c3", "4d7b3db8779f", CheckoutRules.DEFAULT);
+    assertEquals(1, changes.size());
+  }
+
+
+  public void should_not_report_any_changes_when_subrepo_added(@NotNull HgVersion _) throws Exception {
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "4d7b3db8779f", "d350e7209906", CheckoutRules.DEFAULT);
+    assertEquals(1, changes.size());
+  }
+
+
+  public void should_report_subrepo_changes_recursevly(@NotNull HgVersion _) throws Exception {
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "09c256b6163e", "d64d9799c143", CheckoutRules.DEFAULT);
+    assertEquals(7, changes.size());
+
+    assertThat(changes, hasItem(modificationData().withVersion("d64d9799c143").withVcsRootProperties(root.getProperties())));
+
+    Map<String, String> s1props = new HashMap<String, String>(root.getProperties());
+    s1props.put("teamcity.internal.subrepo.path", "r2");
+    s1props.put(Constants.REPOSITORY_PROP, myRemoteRepo3.getCanonicalPath());
+    s1props.put("teamcity.internal.subrepo", "true");
+    assertThat(changes, hasItem(modificationData().withVersion("514c3e09cddf").withVcsRootProperties(s1props)));
+    assertThat(changes, hasItem(modificationData().withVersion("1f9eb39a3921").withVcsRootProperties(s1props)));
+
+    Map<String, String> s2props = new HashMap<String, String>(root.getProperties());
+    s2props.put("teamcity.internal.subrepo.path", "r2");
+    s2props.put(Constants.REPOSITORY_PROP, myRemoteRepo2.getCanonicalPath());
+    s2props.put("teamcity.internal.subrepo", "true");
+    assertThat(changes, hasItem(modificationData().withVersion("ac0003deae69").withVcsRootProperties(s2props)));
+    assertThat(changes, hasItem(modificationData().withVersion("29053b4b29ce").withVcsRootProperties(s2props)));
+  }
+
+
+  public void report_subrepo_changes_without_revsets(@NotNull HgVersion _) throws Exception {
+    ServerPluginConfig pluginConfig = new ServerPluginConfigBuilder()
+            .cachesDir(myTempFiles.createTempDir())
+            .detectSubrepoChanges(true)
+            .dontUseRevsets()
+            .build();
+    myVcs = mercurialSupport().withConfig(pluginConfig).build();
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "d350e7209906", "09c256b6163e", CheckoutRules.DEFAULT);
+    assertEquals(3, changes.size());
+  }
+
+
+  public void report_subrepo_revision_changed(@NotNull HgVersion _) throws Exception {
+    ServerPluginConfig pluginConfig = new ServerPluginConfigBuilder()
+            .cachesDir(myTempFiles.createTempDir())
+            .detectSubrepoChanges(true)
+            .build();
+    myVcs = mercurialSupport().withConfig(pluginConfig).build();
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "09c256b6163e", "d64d9799c143", CheckoutRules.DEFAULT);
+    ModificationData m = changes.get(0);
+    Map<String, String> attrs = m.getAttributes();
+    List<SubrepoConfigChange> subrepoConfigChanges = SubrepoConfigChangesAttributes.readSubrepoConfigChanges(attrs);
+    assertEquals(1, subrepoConfigChanges.size());
+    SubrepoConfigChange subrepoConfigChange = subrepoConfigChanges.get(0);
+    assertThat(subrepoConfigChange.getSubrepoPath(), is("r2"));
+    assertThat(subrepoConfigChange.getCurrentSubrepoRevision(), is("514c3e09cddf"));
+    assertThat(subrepoConfigChange.getPreviousSubrepoRevisions(), is(asList("ebb884b1b691")));
+  }
+
+
+  public void report_subrepo_changes(@NotNull HgVersion _) throws Exception {
+    ServerPluginConfig pluginConfig = new ServerPluginConfigBuilder()
+            .cachesDir(myTempFiles.createTempDir())
+            .detectSubrepoChanges(true)
+            .dontUseRevsets()
+            .build();
+    myVcs = mercurialSupport().withConfig(pluginConfig).build();
+    VcsRoot root = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build();
+    List<ModificationData> changes = myVcs.getCollectChangesPolicy().collectChanges(root, "09c256b6163e", "d64d9799c143", CheckoutRules.DEFAULT);
+    assertEquals(5, changes.size());
+
+    assertThat(changes, hasItem(modificationData().withVersion("d64d9799c143").withVcsRootProperties(root.getProperties())));
+
+    Map<String, String> subrepoRootProperties = new HashMap<String, String>(root.getProperties());
+    subrepoRootProperties.put("teamcity.internal.subrepo.path", "r2");
+    subrepoRootProperties.put(Constants.REPOSITORY_PROP, myRemoteRepo3.getCanonicalPath());
+    subrepoRootProperties.put("teamcity.internal.subrepo", "true");
+    assertThat(changes, hasItem(modificationData().withVersion("514c3e09cddf").withVcsRootProperties(subrepoRootProperties)));
+    assertThat(changes, hasItem(modificationData().withVersion("1f9eb39a3921").withVcsRootProperties(subrepoRootProperties)));
+  }
+}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/UnrelatedResitoriesTest.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/UnrelatedResitoriesTest.java	Mon Mar 18 12:08:16 2013 +0400
@@ -8,7 +8,6 @@
 import jetbrains.buildServer.vcs.VcsException;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import org.jetbrains.annotations.NotNull;
-import org.jmock.Mockery;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -16,6 +15,7 @@
 import java.io.File;
 import java.io.IOException;
 
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
 
@@ -25,12 +25,11 @@
 @Test
 public class UnrelatedResitoriesTest {
 
-  private final static String CURRENT_VERSION_OF_NEW_REPO = "a2672ee13212";
+  private final static String CURRENT_VERSION_OF_NEW_REPO = "4780519e01aa";
   private MercurialVcsSupport myVcs;
   private TempFiles myTempFiles;
   private File myRepositoryLocation;
   private VcsRootImpl myRoot;
-  private Mockery myContext;
   private ServerPluginConfig myPluginConfig;
 
   static {
@@ -39,7 +38,6 @@
 
   @BeforeMethod
   public void setUp() throws Exception {
-    myContext = new Mockery();
     myTempFiles = new TempFiles();
     myPluginConfig = new ServerPluginConfigBuilder()
             .cachesDir(myTempFiles.createTempDir())
@@ -61,7 +59,7 @@
     syncRepository();
     repositoryBecamesUnrelated();
     String currentVersion = syncRepository();
-    assertEquals("4780519e01aa", currentVersion);
+    assertEquals(CURRENT_VERSION_OF_NEW_REPO, currentVersion);
   }
 
 
@@ -70,7 +68,7 @@
     String currentVersionOfOldRepo = syncRepository();
     repositoryBecamesUnrelated();
     String currentVersionOfNewRepo = syncRepository();
-    assertTrue(myVcs.collectChanges(myRoot, currentVersionOfOldRepo, currentVersionOfNewRepo, CheckoutRules.DEFAULT).isEmpty());
+    assertTrue(myVcs.getCollectChangesPolicy().collectChanges(myRoot, currentVersionOfOldRepo, currentVersionOfNewRepo, CheckoutRules.DEFAULT).isEmpty());
   }
 
 
@@ -88,6 +86,6 @@
   }
 
   private MercurialVcsSupport createVcs() throws IOException {
-    return Util.createMercurialServerSupport(myContext, myPluginConfig);
+    return mercurialSupport().withConfig(myPluginConfig).build();
   }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Util.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Util.java	Mon Mar 18 12:08:16 2013 +0400
@@ -1,28 +1,17 @@
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
 import jetbrains.buildServer.TempFiles;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettings;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory;
-import jetbrains.buildServer.serverSide.BuildServerListener;
-import jetbrains.buildServer.serverSide.SBuildServer;
-import jetbrains.buildServer.util.EventDispatcher;
 import jetbrains.buildServer.util.FileUtil;
-import jetbrains.buildServer.util.cache.ResetCacheRegister;
 import jetbrains.buildServer.vcs.CheckoutRules;
 import jetbrains.buildServer.vcs.VcsException;
-import jetbrains.buildServer.vcs.VcsManager;
 import jetbrains.buildServer.vcs.VcsRoot;
 import jetbrains.buildServer.vcs.patches.PatchBuilderImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jmock.Expectations;
-import org.jmock.Mockery;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
 
 /**
  * @author dmitry.neverov
@@ -41,28 +30,6 @@
   }
 
 
-  public static MercurialVcsSupport createMercurialServerSupport(@NotNull Mockery context, ServerPluginConfig config) throws IOException {
-    return createMercurialServerSupport(context, config, new RepoFactory(config, new TestCommandSettingsFactory()));
-  }
-
-
-  public static MercurialVcsSupport createMercurialServerSupport(@NotNull Mockery context, @NotNull ServerPluginConfig config, @NotNull RepoFactory repoFactory) throws IOException {
-    VcsManager vcsManager = context.mock(VcsManager.class);
-    final SBuildServer server = context.mock(SBuildServer.class);
-    final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
-    context.checking(new Expectations() {{
-      allowing(server).getExecutor(); will(returnValue(executor));
-    }});
-    EventDispatcher<BuildServerListener> dispatcher = EventDispatcher.create(BuildServerListener.class);
-    HgVcsRootFactory hgVcsRootFactory = new HgVcsRootFactory(config);
-    MirrorManagerImpl mirrorManager = new MirrorManagerImpl(config);
-    ServerHgPathProvider hgPathProvider = new ServerHgPathProvider(config);
-    HgTestConnectionSupport testConnection = new HgTestConnectionSupport(hgVcsRootFactory, repoFactory, mirrorManager, hgPathProvider);
-    return new MercurialVcsSupport(vcsManager, server, dispatcher, new ResetCacheRegister(), config, hgPathProvider,
-            repoFactory, mirrorManager, hgVcsRootFactory, testConnection);
-  }
-
-
   public static File copyRepository(@NotNull TempFiles tempFiles, @NotNull String repPath) throws IOException {
     File tempDir = tempFiles.createTempDir();
     copyRepository(new File(repPath), tempDir);
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/VcsRootBuilder.java	Mon Mar 18 12:08:16 2013 +0400
@@ -1,14 +1,13 @@
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
+import java.io.File;
+import java.io.IOException;
 import jetbrains.buildServer.vcs.SVcsRoot;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 
-import java.io.File;
-import java.io.IOException;
-
 /**
  * @author dmitry.neverov
  */
@@ -23,6 +22,7 @@
   private String myUserForTag;
   private boolean myUncompressed = true;
   private File myCloneRepositoryTo;
+  private boolean myDetectSubrepoChanges = false;
 
   public static VcsRootBuilder vcsRoot() {
     return new VcsRootBuilder();
@@ -37,6 +37,7 @@
     vcsRoot.addProperty(Constants.BRANCH_NAME_PROP, myBranch);
     vcsRoot.addProperty(Constants.USER_FOR_TAG, myUserForTag);
     vcsRoot.addProperty(Constants.UNCOMPRESSED_TRANSFER, String.valueOf(myUncompressed));
+    vcsRoot.addProperty(Constants.DETECT_SUBREPO_CHANGES, String.valueOf(myDetectSubrepoChanges));
     if (myCloneRepositoryTo != null)
       vcsRoot.addProperty(Constants.SERVER_CLONE_PATH_PROP, String.valueOf(myCloneRepositoryTo.getAbsolutePath()));
     return vcsRoot;
@@ -46,6 +47,7 @@
   public SVcsRoot build(Mockery context) {
     final SVcsRoot root = context.mock(SVcsRoot.class, "SVcsRoot" + myRootId);
     context.checking(new Expectations() {{
+      allowing(root).describe(false); will(returnValue("toString"));
       allowing(root).getVcsName(); will(returnValue(Constants.VCS_NAME));
       allowing(root).getProperty(with(Constants.REPOSITORY_PROP)); will(returnValue(myRepository));
       allowing(root).getProperty(with(Constants.HG_COMMAND_PATH_PROP)); will(returnValue(myHgPath));
@@ -55,6 +57,7 @@
       allowing(root).getProperty(with(Constants.PASSWORD)); will(returnValue(myPassword));
       allowing(root).getProperty(with(Constants.UNCOMPRESSED_TRANSFER)); will(returnValue(null));
       allowing(root).getProperty(with(Constants.USER_FOR_TAG)); will(returnValue(myUserForTag));
+      allowing(root).getProperty(with(Constants.DETECT_SUBREPO_CHANGES)); will(returnValue(String.valueOf(myDetectSubrepoChanges)));
     }});
     if (myCloneRepositoryTo != null) {
       context.checking(new Expectations() {{
@@ -111,4 +114,10 @@
     myCloneRepositoryTo = cloneTo;
     return this;
   }
+
+
+  public VcsRootBuilder withSubrepoChanges(boolean detectSubrepoChanges) {
+    myDetectSubrepoChanges = detectSubrepoChanges;
+    return this;
+  }
 }
--- a/mercurial-tests/src/testng.xml	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/src/testng.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -26,6 +26,8 @@
       <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.ListFilesSupportTest"/>
       <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.RevisionFormatTest"/>
       <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.HgFileUtilTest"/>
+      <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.SubrepoChangesTest"/>
+      <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.HgRepoTest"/>
       <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialXmlLogParserTest"/>
       <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.HgVcsRootFactoryTest"/>
     </classes>
Binary file mercurial-tests/testData/bookmarks/1/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/cache/branchheads	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+e052c89b1159cc0b3aae6ffcf68a04768fc64325 5
+e052c89b1159cc0b3aae6ffcf68a04768fc64325 default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/cache/tags	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+5 e052c89b1159cc0b3aae6ffcf68a04768fc64325
+
Binary file mercurial-tests/testData/bookmarks/1/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/last-message.txt	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+merge 3
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/requires	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/1/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/1/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/1/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/store/fncache	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/1/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/undo.branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/undo.desc	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+5
+commit
Binary file mercurial-tests/testData/bookmarks/1/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/2/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/bookmarks.current	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+bookmark1
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/cache/branchheads	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e 6
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/cache/tags	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+6 7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e
+
Binary file mercurial-tests/testData/bookmarks/2/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/last-message.txt	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+4
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/requires	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/2/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/2/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/2/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/store/fncache	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/2/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/undo.bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/undo.branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/undo.desc	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+6
+commit
Binary file mercurial-tests/testData/bookmarks/2/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/3/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/cache/branchheads	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e 6
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/cache/tags	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+6 7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e
+
Binary file mercurial-tests/testData/bookmarks/3/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/last-message.txt	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+4
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/requires	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/3/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/3/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/3/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/store/fncache	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/3/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/undo.bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/undo.branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/undo.desc	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+6
+commit
Binary file mercurial-tests/testData/bookmarks/3/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/4/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark1
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/bookmarks.current	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/cache/branchheads	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e 6
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/cache/tags	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+6 7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e
+
Binary file mercurial-tests/testData/bookmarks/4/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/last-message.txt	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+4
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/requires	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/4/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/4/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/4/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/store/fncache	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/4/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/undo.bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/undo.branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/undo.desc	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+6
+commit
Binary file mercurial-tests/testData/bookmarks/4/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/5/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark1
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/bookmarks.current	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/cache/branchheads	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,3 @@
+f63a14e873d65cbad50c3a15a4b7336d773e034f 7
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
+f63a14e873d65cbad50c3a15a4b7336d773e034f bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/cache/tags	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+7 f63a14e873d65cbad50c3a15a4b7336d773e034f
+
Binary file mercurial-tests/testData/bookmarks/5/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/last-message.txt	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+Create branch bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/requires	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/5/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/5/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/5/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/store/fncache	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/5/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/undo.bookmarks	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark1
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/undo.branch	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,1 @@
+bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/undo.desc	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,2 @@
+7
+commit
Binary file mercurial-tests/testData/bookmarks/5/hg/undo.dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/README	Mon Mar 18 12:08:16 2013 +0400
@@ -0,0 +1,69 @@
+1) repository with 2 bookmarks (base for tests):
+
+o    5:e052c89b1159 merge 3 [bookmark2]
+|\
+| o  4:e9f8f67888f5 test 1
+| |
+o |  3:15b4a116520d 3 [bookmark1]
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
+
+
+2) bookmark1 udpated:
+
+o  6:7597a4da7195 4 [bookmark1]
+|
+o    5:e052c89b1159 merge 3 [bookmark2]
+|\
+| o  4:e9f8f67888f5 test 1
+| |
+o |  3:15b4a116520d 3
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
+
+
+3) all bookmarks removed
+
+
+4) bookmark1 diverged
+
+o  6:7597a4da7195 4 [bookmark2]
+|
+o    5:e052c89b1159 merge 3
+|\
+| o  4:e9f8f67888f5 test 1 [bookmark1]
+| |
+o |  3:15b4a116520d 3
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
+
+
+5) branch with name 'bookmark2' created:
+
+o  7:f63a14e873d6 Create branch bookmark2 (bookmark2)
+|
+o  6:7597a4da7195 4 [bookmark2]
+|
+o    5:e052c89b1159 merge 3
+|\
+| o  4:e9f8f67888f5 test 1 [bookmark1]
+| |
+o |  3:15b4a116520d 3
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
\ No newline at end of file
--- a/mercurial-tests/testData/subrepos/README	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/testData/subrepos/README	Mon Mar 18 12:08:16 2013 +0400
@@ -1,13 +1,21 @@
 r1 history:
+5:d64d9799c143 Recursive subrepos                           <- subrepository r2 = ../r3 (514c3e09cddf)
+4:09c256b6163e Subrepo update                               <- subrepository r2 = ../r3 (ebb884b1b691)
 3:d350e7209906 Add different subrepository in the same path <- subrepository r2 = ../r3 (9e4a2fef1a1c)
 2:4d7b3db8779f Remove subrepository                         <- subrepository removed
 1:34017377d9c3 Add subrepository                            <- subrepository r2 = ../r2 (916933c1dd8e)
 0:e4eced2b7381 Initial commit
 
 r2 history:
+2:ac0003deae69 three
+1:29053b4b29ce two
 0:916933c1dd8e Initial commit
 
 r3 history:
+4:514c3e09cddf Upgrade subrepo                              <- subrepository r2 = ../r2 (ac0003deae69)
+3:1f9eb39a3921 Add subrepo                                  <- subrepository r2 = ../r2 (916933c1dd8e)
+2:ebb884b1b691 two
+1:f41168ce47b7 one
 0:9e4a2fef1a1c Initial commit
 
 
Binary file mercurial-tests/testData/subrepos/r1/hg/dirstate has changed
Binary file mercurial-tests/testData/subrepos/r1/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/subrepos/r1/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/subrepos/r1/hg/store/data/.hgsubstate.i has changed
Binary file mercurial-tests/testData/subrepos/r1/hg/store/undo has changed
--- a/mercurial-tests/testData/subrepos/r1/hg/undo.desc	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/testData/subrepos/r1/hg/undo.desc	Mon Mar 18 12:08:16 2013 +0400
@@ -1,2 +1,2 @@
-3
+4
 commit
Binary file mercurial-tests/testData/subrepos/r1/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/subrepos/r2/hg/dirstate has changed
Binary file mercurial-tests/testData/subrepos/r2/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/subrepos/r2/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/subrepos/r2/hg/store/data/b.i has changed
Binary file mercurial-tests/testData/subrepos/r2/hg/store/undo has changed
Binary file mercurial-tests/testData/subrepos/r3/hg/dirstate has changed
Binary file mercurial-tests/testData/subrepos/r3/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/subrepos/r3/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/subrepos/r3/hg/store/data/.hgsub.i has changed
Binary file mercurial-tests/testData/subrepos/r3/hg/store/data/.hgsubstate.i has changed
Binary file mercurial-tests/testData/subrepos/r3/hg/store/data/c.i has changed
--- a/mercurial-tests/testData/subrepos/r3/hg/store/fncache	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial-tests/testData/subrepos/r3/hg/store/fncache	Mon Mar 18 12:08:16 2013 +0400
@@ -1,1 +1,3 @@
+data/.hgsubstate.i
+data/.hgsub.i
 data/c.i
Binary file mercurial-tests/testData/subrepos/r3/hg/store/undo has changed
Binary file mercurial-tests/testData/subrepos/r3/hg/undo.dirstate has changed
--- a/mercurial.ipr	Mon Mar 18 12:05:23 2013 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="AntConfiguration">
-    <defaultAnt bundledAnt="true" />
-    <buildFile url="file://$PROJECT_DIR$/build.xml">
-      <additionalClassPath />
-      <antReference projectDefault="true" />
-      <customJdkName value="" />
-      <maximumHeapSize value="128" />
-      <maximumStackSize value="32" />
-      <properties />
-    </buildFile>
-  </component>
-  <component name="BuildJarProjectSettings">
-    <option name="BUILD_JARS_ON_MAKE" value="false" />
-  </component>
-  <component name="ChangeBrowserSettings">
-    <option name="MAIN_SPLITTER_PROPORTION" value="0.3" />
-    <option name="MESSAGES_SPLITTER_PROPORTION" value="0.8" />
-    <option name="USE_DATE_BEFORE_FILTER" value="false" />
-    <option name="USE_DATE_AFTER_FILTER" value="false" />
-    <option name="USE_CHANGE_BEFORE_FILTER" value="false" />
-    <option name="USE_CHANGE_AFTER_FILTER" value="false" />
-    <option name="DATE_BEFORE" value="" />
-    <option name="DATE_AFTER" value="" />
-    <option name="CHANGE_BEFORE" value="" />
-    <option name="CHANGE_AFTER" value="" />
-    <option name="USE_USER_FILTER" value="false" />
-    <option name="USER" value="" />
-  </component>
-  <component name="ClearCaseSharedConfig">
-    <option name="myUseUcmModel" value="true" />
-  </component>
-  <component name="CodeStyleProjectProfileManger">
-    <option name="PROJECT_PROFILE" />
-    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
-  </component>
-  <component name="CompilerConfiguration">
-    <option name="DEFAULT_COMPILER" value="Javac" />
-    <resourceExtensions>
-      <entry name=".+\.(properties|xml|html|dtd|tld)" />
-      <entry name=".+\.(gif|png|jpeg|jpg)" />
-    </resourceExtensions>
-    <wildcardResourcePatterns>
-      <entry name="?*.properties" />
-      <entry name="?*.xml" />
-      <entry name="?*.gif" />
-      <entry name="?*.png" />
-      <entry name="?*.jpeg" />
-      <entry name="?*.jpg" />
-      <entry name="?*.html" />
-      <entry name="?*.dtd" />
-      <entry name="?*.tld" />
-      <entry name="?*.jsp" />
-      <entry name="?*.tag" />
-      <entry name="?*.template" />
-    </wildcardResourcePatterns>
-    <annotationProcessing>
-      <profile default="true" name="Default" enabled="false">
-        <processorPath useClasspath="true" />
-      </profile>
-    </annotationProcessing>
-  </component>
-  <component name="CopyrightManager" default="">
-    <module2copyright />
-  </component>
-  <component name="DependenciesAnalyzeManager">
-    <option name="myForwardDirection" value="false" />
-  </component>
-  <component name="DependencyValidationManager">
-    <option name="SKIP_IMPORT_STATEMENTS" value="false" />
-  </component>
-  <component name="EclipseCompilerSettings">
-    <option name="GENERATE_NO_WARNINGS" value="true" />
-    <option name="DEPRECATION" value="false" />
-  </component>
-  <component name="EclipseEmbeddedCompilerSettings">
-    <option name="DEBUGGING_INFO" value="true" />
-    <option name="GENERATE_NO_WARNINGS" value="true" />
-    <option name="DEPRECATION" value="false" />
-    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
-    <option name="MAXIMUM_HEAP_SIZE" value="128" />
-  </component>
-  <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
-  <component name="EntryPointsManager">
-    <entry_points version="2.0" />
-  </component>
-  <component name="ErrorOptionsConfigurable.UI">
-    <option name="proportions">
-      <SplitterProportionsDataImpl />
-    </option>
-  </component>
-  <component name="ExportToHTMLSettings">
-    <option name="PRINT_LINE_NUMBERS" value="false" />
-    <option name="OPEN_IN_BROWSER" value="false" />
-    <option name="OUTPUT_DIRECTORY" />
-  </component>
-  <component name="GlobalLibrariesConfigurable.UI">
-    <option name="proportions">
-      <SplitterProportionsDataImpl />
-    </option>
-  </component>
-  <component name="IdProvider" IDEtalkID="317BB29ECB7DA19EFFA340ECF52563C6" />
-  <component name="InspectionProjectProfileManager">
-    <profiles>
-      <profile version="1.0" is_locked="false">
-        <option name="myName" value="Project Default" />
-        <option name="myLocal" value="false" />
-        <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
-          <option name="processCode" value="true" />
-          <option name="processLiterals" value="true" />
-          <option name="processComments" value="true" />
-        </inspection_tool>
-      </profile>
-    </profiles>
-    <option name="PROJECT_PROFILE" value="Project Default" />
-    <option name="USE_PROJECT_PROFILE" value="true" />
-    <version value="1.0" />
-    <list size="6">
-      <item index="0" class="java.lang.String" itemvalue="TYPO" />
-      <item index="1" class="java.lang.String" itemvalue="WEAK WARNING" />
-      <item index="2" class="java.lang.String" itemvalue="INFO" />
-      <item index="3" class="java.lang.String" itemvalue="WARNING" />
-      <item index="4" class="java.lang.String" itemvalue="ERROR" />
-      <item index="5" class="java.lang.String" itemvalue="SERVER PROBLEM" />
-    </list>
-  </component>
-  <component name="JavadocGenerationManager">
-    <option name="OUTPUT_DIRECTORY" />
-    <option name="OPTION_SCOPE" value="protected" />
-    <option name="OPTION_HIERARCHY" value="true" />
-    <option name="OPTION_NAVIGATOR" value="true" />
-    <option name="OPTION_INDEX" value="true" />
-    <option name="OPTION_SEPARATE_INDEX" value="true" />
-    <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
-    <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
-    <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
-    <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
-    <option name="OPTION_DEPRECATED_LIST" value="true" />
-    <option name="OTHER_OPTIONS" value="" />
-    <option name="HEAP_SIZE" />
-    <option name="LOCALE" />
-    <option name="OPEN_IN_BROWSER" value="true" />
-  </component>
-  <component name="JdkListConfigurable.UI">
-    <option name="proportions">
-      <SplitterProportionsDataImpl />
-    </option>
-  </component>
-  <component name="LogConsolePreferences">
-    <option name="FILTER_ERRORS" value="false" />
-    <option name="FILTER_WARNINGS" value="false" />
-    <option name="FILTER_INFO" value="true" />
-    <option name="CUSTOM_FILTER" />
-  </component>
-  <component name="ModuleStructureConfigurable.UI">
-    <option name="proportions">
-      <SplitterProportionsDataImpl />
-    </option>
-  </component>
-  <component name="Palette2">
-    <group name="Swing">
-      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
-      </item>
-      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
-      </item>
-      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
-      </item>
-      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
-        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
-      </item>
-      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
-        <initial-values>
-          <property name="text" value="Button" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
-        <initial-values>
-          <property name="text" value="RadioButton" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
-        <initial-values>
-          <property name="text" value="CheckBox" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
-        <initial-values>
-          <property name="text" value="Label" />
-        </initial-values>
-      </item>
-      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
-          <preferred-size width="150" height="-1" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
-          <preferred-size width="150" height="-1" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
-          <preferred-size width="150" height="-1" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
-      </item>
-      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
-          <preferred-size width="150" height="50" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
-          <preferred-size width="200" height="200" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
-          <preferred-size width="200" height="200" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
-      </item>
-      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
-      </item>
-      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
-      </item>
-      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
-      </item>
-      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
-          <preferred-size width="-1" height="20" />
-        </default-constraints>
-      </item>
-      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
-        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
-      </item>
-      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
-        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
-      </item>
-    </group>
-  </component>
-  <component name="PerforceChangeBrowserSettings">
-    <option name="USE_CLIENT_FILTER" value="true" />
-    <option name="CLIENT" value="" />
-  </component>
-  <component name="ProjectDetails">
-    <option name="projectName" value="mercurial" />
-  </component>
-  <component name="ProjectDictionaryState">
-    <dictionary name="Pavel.Sher" />
-  </component>
-  <component name="ProjectKey">
-    <option name="state" value="project://C:\Work\mercurial\mercurial.ipr" />
-  </component>
-  <component name="ProjectLibrariesConfigurable.UI">
-    <option name="proportions">
-      <SplitterProportionsDataImpl />
-    </option>
-  </component>
-  <component name="ProjectModuleManager">
-    <modules>
-      <module fileurl="file://$PROJECT_DIR$/main.iml" filepath="$PROJECT_DIR$/main.iml" />
-      <module fileurl="file://$PROJECT_DIR$/mercurial-agent/mercurial-agent.iml" filepath="$PROJECT_DIR$/mercurial-agent/mercurial-agent.iml" />
-      <module fileurl="file://$PROJECT_DIR$/mercurial-common/mercurial-common.iml" filepath="$PROJECT_DIR$/mercurial-common/mercurial-common.iml" />
-      <module fileurl="file://$PROJECT_DIR$/mercurial-server/mercurial-server.iml" filepath="$PROJECT_DIR$/mercurial-server/mercurial-server.iml" />
-      <module fileurl="file://$PROJECT_DIR$/mercurial-tests/mercurial-tests.iml" filepath="$PROJECT_DIR$/mercurial-tests/mercurial-tests.iml" />
-    </modules>
-  </component>
-  <component name="ProjectResources">
-    <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
-  </component>
-  <component name="ProjectRootConfigurable.UI">
-    <option name="proportions">
-      <SplitterProportionsDataImpl />
-    </option>
-  </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK" />
-  <component name="ResourceManagerContainer">
-    <option name="myResourceBundles">
-      <value>
-        <list size="0" />
-      </value>
-    </option>
-  </component>
-  <component name="ScopeChooserConfigurable.UI">
-    <option name="proportions">
-      <SplitterProportionsDataImpl />
-    </option>
-  </component>
-  <component name="Struts Assistant">
-    <option name="showInputs" value="true" />
-    <option name="resources">
-      <value>
-        <option name="strutsPath" />
-        <option name="strutsHelp" />
-      </value>
-    </option>
-    <option name="selectedTaglibs" />
-    <option name="selectedTaglibs" />
-    <option name="myStrutsValidationEnabled" value="true" />
-    <option name="myTilesValidationEnabled" value="true" />
-    <option name="myValidatorValidationEnabled" value="true" />
-    <option name="myReportErrorsAsWarnings" value="true" />
-  </component>
-  <component name="SvnBranchConfigurationManager">
-    <option name="myVersion" value="123" />
-    <option name="mySupportsUserInfoFilter" value="true" />
-  </component>
-  <component name="SvnChangesBrowserSettings">
-    <option name="USE_AUTHOR_FIELD" value="true" />
-    <option name="AUTHOR" value="" />
-    <option name="LOCATION" value="" />
-    <option name="USE_PROJECT_SETTINGS" value="true" />
-    <option name="USE_ALTERNATE_LOCATION" value="false" />
-  </component>
-  <component name="TeamCityRootDirectoryHolder">
-    <option name="myRelativeRootDirectory" />
-  </component>
-  <component name="VCS.FileViewConfiguration">
-    <option name="SELECTED_STATUSES" value="DEFAULT" />
-    <option name="SELECTED_COLUMNS" value="DEFAULT" />
-    <option name="SHOW_FILTERS" value="true" />
-    <option name="CUSTOMIZE_VIEW" value="true" />
-    <option name="SHOW_FILE_HISTORY_AS_TREE" value="true" />
-  </component>
-  <component name="VcsDirectoryMappings">
-    <mapping directory="" vcs="hg4idea" />
-  </component>
-  <component name="WebServicesPlugin" addRequiredLibraries="true" />
-  <component name="com.intellij.ide.util.scopeChooser.ScopeChooserConfigurable" proportions="" version="1">
-    <option name="myLastEditedConfigurable" />
-  </component>
-  <component name="com.intellij.jsf.UserDefinedFacesConfigs">
-    <option name="USER_DEFINED_CONFIGS">
-      <value>
-        <list size="0" />
-      </value>
-    </option>
-  </component>
-  <component name="com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectRootMasterDetailsConfigurable" proportions="" version="1">
-    <option name="myPlainMode" value="false" />
-    <option name="myLastEditedConfigurable" />
-  </component>
-  <component name="com.intellij.profile.ui.ErrorOptionsConfigurable" proportions="" version="1">
-    <option name="myLastEditedConfigurable" />
-  </component>
-  <component name="libraryTable">
-    <library name="IDEA-openapi">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/resources_en.jar!/" />
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/util.jar!/" />
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/openapi.jar!/" />
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/annotations.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES />
-    </library>
-    <library name="jdom">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/jdom.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES />
-    </library>
-    <library name="JMock">
-      <CLASSES>
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-library-1.1.jar!/" />
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-core-1.1.jar!/" />
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/jmock-2.5.1.jar!/" />
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/jmock-SNAPSHOT.jar!/" />
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-integration-1.1.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES>
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/hamcrest-integration-1.1.jar!/" />
-      </SOURCES>
-    </library>
-    <library name="JUnit">
-      <CLASSES>
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/junit-3.8.1.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES />
-    </library>
-    <library name="Log4j">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-1.2.12.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES />
-    </library>
-    <library name="TeamCity-impl">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/patches-impl.jar!/" />
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove4j.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES />
-    </library>
-    <library name="TeamCity-TestsAPI">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/devPackage/tests/patches-test.jar!/" />
-        <root url="jar://$TeamCityDistribution$/devPackage/tests/tests-support.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES />
-    </library>
-    <library name="TeamCityAPI-agent">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/devPackage/agent-api.jar!/" />
-        <root url="jar://$TeamCityDistribution$/buildAgent/lib/agent.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES>
-        <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
-      </SOURCES>
-    </library>
-    <library name="TeamCityAPI-common">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/devPackage/common-api.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES>
-        <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
-      </SOURCES>
-    </library>
-    <library name="TeamCityAPI-server">
-      <CLASSES>
-        <root url="jar://$TeamCityDistribution$/devPackage/server-api.jar!/" />
-        <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES>
-        <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
-      </SOURCES>
-    </library>
-    <library name="TestNG">
-      <CLASSES>
-        <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/testng-5.7-jdk15.jar!/" />
-      </CLASSES>
-      <JAVADOC />
-      <SOURCES />
-    </library>
-  </component>
-  <component name="testng.defaultConfiguration">
-    <outputDirectory />
-    <properties />
-  </component>
-</project>
-
--- a/mercurial.xml	Mon Mar 18 12:05:23 2013 +0400
+++ b/mercurial.xml	Mon Mar 18 12:08:16 2013 +0400
@@ -1,644 +1,601 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="mercurial" default="all">
-  
-  
-  <property file="mercurial.properties"/>
-  <!-- Uncomment the following property if no tests compilation is needed -->
-  <!-- 
-  <property name="skip.tests" value="true"/>
-   -->
-  
-  <!-- Compiler options -->
-  
-  <property name="compiler.debug" value="on"/>
-  <property name="compiler.generate.no.warnings" value="off"/>
-  <property name="compiler.args" value=""/>
-  <property name="compiler.max.memory" value="128m"/>
-  <patternset id="ignored.files">
-    <exclude name="**/CVS/**"/>
-    <exclude name="**/SCCS/**"/>
-    <exclude name="**/RCS/**"/>
-    <exclude name="**/rcs/**"/>
-    <exclude name="**/.DS_Store/**"/>
-    <exclude name="**/.svn/**"/>
-    <exclude name="**/.pyc/**"/>
-    <exclude name="**/.pyo/**"/>
-    <exclude name="**/*.pyc/**"/>
-    <exclude name="**/*.pyo/**"/>
-    <exclude name="**/.git/**"/>
-    <exclude name="**/*.hprof/**"/>
-    <exclude name="**/_svn/**"/>
-    <exclude name="**/.hg/**"/>
-    <exclude name="**/.sbas/**"/>
-    <exclude name="**/.IJI.*/**"/>
-    <exclude name="**/vssver.scc/**"/>
-    <exclude name="**/vssver2.scc/**"/>
-    <exclude name="**/*.orig/**"/>
-    <exclude name="**/*.lib/**"/>
-    <exclude name="**/*~/**"/>
-    <exclude name="**/__pycache__/**"/>
-    <exclude name="**/.bundle/**"/>
-    <exclude name="**/*.rbc/**"/>
-  </patternset>
-  <patternset id="library.patterns">
-    <include name="*.war"/>
-    <include name="*.ear"/>
-    <include name="*.apk"/>
-    <include name="*.zip"/>
-    <include name="*.swc"/>
-    <include name="*.egg"/>
-    <include name="*.jar"/>
-  </patternset>
-  <patternset id="compiler.resources">
-    <include name="**/?*.properties"/>
-    <include name="**/?*.xml"/>
-    <include name="**/?*.gif"/>
-    <include name="**/?*.png"/>
-    <include name="**/?*.jpeg"/>
-    <include name="**/?*.jpg"/>
-    <include name="**/?*.html"/>
-    <include name="**/?*.dtd"/>
-    <include name="**/?*.tld"/>
-    <include name="**/?*.jsp"/>
-    <include name="**/?*.tag"/>
-    <include name="**/?*.template"/>
-  </patternset>
-  
-  <!-- JDK definitions -->
-  
-  <property name="jdk.bin.1.5" value="${jdk.home.1.5}/bin"/>
-  <path id="jdk.classpath.1.5">
-    <fileset dir="${jdk.home.1.5}">
-      <include name="jre/lib/rt.jar"/>
-      <include name="jre/lib/jce.jar"/>
-      <include name="jre/lib/deploy.jar"/>
-      <include name="jre/lib/javaws.jar"/>
-      <include name="jre/lib/jsse.jar"/>
-      <include name="jre/lib/charsets.jar"/>
-      <include name="jre/lib/plugin.jar"/>
-      <include name="jre/lib/ext/localedata.jar"/>
-      <include name="jre/lib/ext/sunpkcs11.jar"/>
-      <include name="jre/lib/ext/sunjce_provider.jar"/>
-      <include name="jre/lib/ext/dnsns.jar"/>
-    </fileset>
-  </path>
-  
-  <property name="project.jdk.home" value="${jdk.home.1.5}"/>
-  <property name="project.jdk.bin" value="${jdk.bin.1.5}"/>
-  <property name="project.jdk.classpath" value="jdk.classpath.1.5"/>
-  
-  
-  <!-- Project Libraries -->
-  
-  <path id="library.idea-openapi.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/annotations.jar"/>
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/openapi.jar"/>
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/resources_en.jar"/>
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/util.jar"/>
-  </path>
-  
-  <path id="library.jdom.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/jdom.jar"/>
-  </path>
-  
-  <path id="library.jmock.classpath">
-    <pathelement location="${basedir}/mercurial-tests/lib/hamcrest-core-1.1.jar"/>
-    <pathelement location="${basedir}/mercurial-tests/lib/hamcrest-integration-1.1.jar"/>
-    <pathelement location="${basedir}/mercurial-tests/lib/hamcrest-library-1.1.jar"/>
-    <pathelement location="${basedir}/mercurial-tests/lib/jmock-2.5.1.jar"/>
-    <pathelement location="${basedir}/mercurial-tests/lib/jmock-SNAPSHOT.jar"/>
-  </path>
-  
-  <path id="library.junit.classpath">
-    <pathelement location="${basedir}/mercurial-tests/lib/junit-3.8.1.jar"/>
-  </path>
-  
-  <path id="library.log4j.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/log4j-1.2.12.jar"/>
-  </path>
-  
-  <path id="library.teamcity-impl.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/patches-impl.jar"/>
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/trove4j.jar"/>
-  </path>
-  
-  <path id="library.teamcity-testsapi.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/devPackage/tests/patches-test.jar"/>
-    <pathelement location="${path.variable.teamcitydistribution}/devPackage/tests/tests-support.jar"/>
-  </path>
-  
-  <path id="library.teamcityapi-agent.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/buildAgent/lib/agent.jar"/>
-    <pathelement location="${path.variable.teamcitydistribution}/devPackage/agent-api.jar"/>
-  </path>
-  
-  <path id="library.teamcityapi-common.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/devPackage/common-api.jar"/>
-  </path>
-  
-  <path id="library.teamcityapi-server.classpath">
-    <pathelement location="${path.variable.teamcitydistribution}/devPackage/server-api.jar"/>
-    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/server.jar"/>
-  </path>
-  
-  <path id="library.testng.classpath">
-    <pathelement location="${basedir}/mercurial-tests/lib/testng-5.7-jdk15.jar"/>
-  </path>
-  
-  
-  <!-- Global Libraries -->
-  
-  
-  <!-- Application Server Libraries -->
-  
-  <!-- Modules -->
-  
-  
-  <!-- Module main -->
-  
-  <dirname property="module.main.basedir" file="${ant.file}"/>
-  
-  
-  <property name="module.jdk.home.main" value="${project.jdk.home}"/>
-  <property name="module.jdk.bin.main" value="${project.jdk.bin}"/>
-  <property name="module.jdk.classpath.main" value="${project.jdk.classpath}"/>
-  
-  <property name="compiler.args.main" value="${compiler.args}"/>
-  
-  <property name="main.output.dir" value="undefined"/>
-  <property name="main.testoutput.dir" value="undefined"/>
-  
-  <path id="main.module.bootclasspath">
-    <!-- Paths to be included in compilation bootclasspath -->
-  </path>
-  
-  <path id="main.module.production.classpath">
-    <path refid="${module.jdk.classpath.main}"/>
-  </path>
-  
-  <path id="main.runtime.production.module.classpath"/>
-  
-  <path id="main.module.classpath">
-    <path refid="${module.jdk.classpath.main}"/>
-  </path>
-  
-  <path id="main.runtime.module.classpath"/>
-  
-  
-  <patternset id="excluded.from.module.main">
-    <patternset refid="ignored.files"/>
-  </patternset>
-  
-  <patternset id="excluded.from.compilation.main">
-    <patternset refid="excluded.from.module.main"/>
-  </patternset>
-  
-  
-  <target name="compile.module.main" depends="compile.module.main.production,compile.module.main.tests" description="Compile module main"/>
-  
-  <target name="compile.module.main.production" description="Compile module main; production classes"/>
-  
-  <target name="compile.module.main.tests" depends="compile.module.main.production" description="compile module main; test classes" unless="skip.tests"/>
-  
-  <target name="clean.module.main" description="cleanup module">
-    <delete dir="${main.output.dir}"/>
-    <delete dir="${main.testoutput.dir}"/>
-  </target>
-  
-  
-  <!-- Module mercurial-common -->
-  
-  <dirname property="module.mercurial-common.basedir" file="${ant.file}"/>
-  
-  
-  <property name="module.jdk.home.mercurial-common" value="${project.jdk.home}"/>
-  <property name="module.jdk.bin.mercurial-common" value="${project.jdk.bin}"/>
-  <property name="module.jdk.classpath.mercurial-common" value="${project.jdk.classpath}"/>
-  
-  <property name="compiler.args.mercurial-common" value="${compiler.args}"/>
-  
-  <property name="mercurial-common.output.dir" value="${module.mercurial-common.basedir}/mercurial-common/classes"/>
-  <property name="mercurial-common.testoutput.dir" value="${module.mercurial-common.basedir}/mercurial-common/classes"/>
-  
-  <path id="mercurial-common.module.bootclasspath">
-    <!-- Paths to be included in compilation bootclasspath -->
-  </path>
-  
-  <path id="mercurial-common.module.production.classpath">
-    <path refid="${module.jdk.classpath.mercurial-common}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  <path id="mercurial-common.runtime.production.module.classpath">
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  <path id="mercurial-common.module.classpath">
-    <path refid="${module.jdk.classpath.mercurial-common}"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  <path id="mercurial-common.runtime.module.classpath">
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  
-  <patternset id="excluded.from.module.mercurial-common">
-    <patternset refid="ignored.files"/>
-  </patternset>
-  
-  <patternset id="excluded.from.compilation.mercurial-common">
-    <patternset refid="excluded.from.module.mercurial-common"/>
-  </patternset>
-  
-  <path id="mercurial-common.module.sourcepath">
-    <dirset dir="${module.mercurial-common.basedir}/mercurial-common">
-      <include name="src"/>
-    </dirset>
-  </path>
-  
-  
-  <target name="compile.module.mercurial-common" depends="compile.module.mercurial-common.production,compile.module.mercurial-common.tests" description="Compile module mercurial-common"/>
-  
-  <target name="compile.module.mercurial-common.production" description="Compile module mercurial-common; production classes">
-    <mkdir dir="${mercurial-common.output.dir}"/>
-    <javac destdir="${mercurial-common.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true" executable="${module.jdk.bin.mercurial-common}/javac">
-      <compilerarg line="${compiler.args.mercurial-common}"/>
-      <bootclasspath refid="mercurial-common.module.bootclasspath"/>
-      <classpath refid="mercurial-common.module.production.classpath"/>
-      <src refid="mercurial-common.module.sourcepath"/>
-      <patternset refid="excluded.from.compilation.mercurial-common"/>
-    </javac>
-    
-    <copy todir="${mercurial-common.output.dir}">
-      <fileset dir="${module.mercurial-common.basedir}/mercurial-common/src">
-        <patternset refid="compiler.resources"/>
-        <type type="file"/>
-      </fileset>
-    </copy>
-  </target>
-  
-  <target name="compile.module.mercurial-common.tests" depends="compile.module.mercurial-common.production" description="compile module mercurial-common; test classes" unless="skip.tests"/>
-  
-  <target name="clean.module.mercurial-common" description="cleanup module">
-    <delete dir="${mercurial-common.output.dir}"/>
-    <delete dir="${mercurial-common.testoutput.dir}"/>
-  </target>
-  
-  
-  <!-- Module mercurial-agent -->
-  
-  <dirname property="module.mercurial-agent.basedir" file="${ant.file}"/>
-  
-  
-  <property name="module.jdk.home.mercurial-agent" value="${project.jdk.home}"/>
-  <property name="module.jdk.bin.mercurial-agent" value="${project.jdk.bin}"/>
-  <property name="module.jdk.classpath.mercurial-agent" value="${project.jdk.classpath}"/>
-  
-  <property name="compiler.args.mercurial-agent" value="${compiler.args}"/>
-  
-  <property name="mercurial-agent.output.dir" value="${module.mercurial-agent.basedir}/mercurial-agent/classes"/>
-  <property name="mercurial-agent.testoutput.dir" value="${module.mercurial-agent.basedir}/mercurial-agent/classes"/>
-  
-  <path id="mercurial-agent.module.bootclasspath">
-    <!-- Paths to be included in compilation bootclasspath -->
-  </path>
-  
-  <path id="mercurial-agent.module.production.classpath">
-    <path refid="${module.jdk.classpath.mercurial-agent}"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-  </path>
-  
-  <path id="mercurial-agent.runtime.production.module.classpath">
-    <pathelement location="${mercurial-agent.output.dir}"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  <path id="mercurial-agent.module.classpath">
-    <path refid="${module.jdk.classpath.mercurial-agent}"/>
-    <pathelement location="${mercurial-agent.output.dir}"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-  </path>
-  
-  <path id="mercurial-agent.runtime.module.classpath">
-    <pathelement location="${mercurial-agent.output.dir}"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  
-  <patternset id="excluded.from.module.mercurial-agent">
-    <patternset refid="ignored.files"/>
-  </patternset>
-  
-  <patternset id="excluded.from.compilation.mercurial-agent">
-    <patternset refid="excluded.from.module.mercurial-agent"/>
-  </patternset>
-  
-  <path id="mercurial-agent.module.sourcepath">
-    <dirset dir="${module.mercurial-agent.basedir}/mercurial-agent">
-      <include name="src"/>
-    </dirset>
-  </path>
-  
-  
-  <target name="compile.module.mercurial-agent" depends="compile.module.mercurial-agent.production,compile.module.mercurial-agent.tests" description="Compile module mercurial-agent"/>
-  
-  <target name="compile.module.mercurial-agent.production" depends="compile.module.mercurial-common" description="Compile module mercurial-agent; production classes">
-    <mkdir dir="${mercurial-agent.output.dir}"/>
-    <javac destdir="${mercurial-agent.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true" executable="${module.jdk.bin.mercurial-agent}/javac">
-      <compilerarg line="${compiler.args.mercurial-agent}"/>
-      <bootclasspath refid="mercurial-agent.module.bootclasspath"/>
-      <classpath refid="mercurial-agent.module.production.classpath"/>
-      <src refid="mercurial-agent.module.sourcepath"/>
-      <patternset refid="excluded.from.compilation.mercurial-agent"/>
-    </javac>
-    
-    <copy todir="${mercurial-agent.output.dir}">
-      <fileset dir="${module.mercurial-agent.basedir}/mercurial-agent/src">
-        <patternset refid="compiler.resources"/>
-        <type type="file"/>
-      </fileset>
-    </copy>
-  </target>
-  
-  <target name="compile.module.mercurial-agent.tests" depends="compile.module.mercurial-agent.production" description="compile module mercurial-agent; test classes" unless="skip.tests"/>
-  
-  <target name="clean.module.mercurial-agent" description="cleanup module">
-    <delete dir="${mercurial-agent.output.dir}"/>
-    <delete dir="${mercurial-agent.testoutput.dir}"/>
-  </target>
-  
-  
-  <!-- Module mercurial-server -->
-  
-  <dirname property="module.mercurial-server.basedir" file="${ant.file}"/>
-  
-  
-  <property name="module.jdk.home.mercurial-server" value="${project.jdk.home}"/>
-  <property name="module.jdk.bin.mercurial-server" value="${project.jdk.bin}"/>
-  <property name="module.jdk.classpath.mercurial-server" value="${project.jdk.classpath}"/>
-  
-  <property name="compiler.args.mercurial-server" value="${compiler.args}"/>
-  
-  <property name="mercurial-server.output.dir" value="${module.mercurial-server.basedir}/mercurial-server/classes"/>
-  <property name="mercurial-server.testoutput.dir" value="${module.mercurial-server.basedir}/mercurial-server/classes"/>
-  
-  <path id="mercurial-server.module.bootclasspath">
-    <!-- Paths to be included in compilation bootclasspath -->
-  </path>
-  
-  <path id="mercurial-server.module.production.classpath">
-    <path refid="${module.jdk.classpath.mercurial-server}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-  </path>
-  
-  <path id="mercurial-server.runtime.production.module.classpath">
-    <pathelement location="${mercurial-server.output.dir}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  <path id="mercurial-server.module.classpath">
-    <path refid="${module.jdk.classpath.mercurial-server}"/>
-    <pathelement location="${mercurial-server.output.dir}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-  </path>
-  
-  <path id="mercurial-server.runtime.module.classpath">
-    <pathelement location="${mercurial-server.output.dir}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.jdom.classpath"/>
-  </path>
-  
-  
-  <patternset id="excluded.from.module.mercurial-server">
-    <patternset refid="ignored.files"/>
-  </patternset>
-  
-  <patternset id="excluded.from.compilation.mercurial-server">
-    <patternset refid="excluded.from.module.mercurial-server"/>
-  </patternset>
-  
-  <path id="mercurial-server.module.sourcepath">
-    <dirset dir="${module.mercurial-server.basedir}/mercurial-server">
-      <include name="resources"/>
-      <include name="src"/>
-    </dirset>
-  </path>
-  
-  
-  <target name="compile.module.mercurial-server" depends="compile.module.mercurial-server.production,compile.module.mercurial-server.tests" description="Compile module mercurial-server"/>
-  
-  <target name="compile.module.mercurial-server.production" depends="compile.module.mercurial-common" description="Compile module mercurial-server; production classes">
-    <mkdir dir="${mercurial-server.output.dir}"/>
-    <javac destdir="${mercurial-server.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true" executable="${module.jdk.bin.mercurial-server}/javac">
-      <compilerarg line="${compiler.args.mercurial-server}"/>
-      <bootclasspath refid="mercurial-server.module.bootclasspath"/>
-      <classpath refid="mercurial-server.module.production.classpath"/>
-      <src refid="mercurial-server.module.sourcepath"/>
-      <patternset refid="excluded.from.compilation.mercurial-server"/>
-    </javac>
-    
-    <copy todir="${mercurial-server.output.dir}">
-      <fileset dir="${module.mercurial-server.basedir}/mercurial-server/resources">
-        <patternset refid="compiler.resources"/>
-        <type type="file"/>
-      </fileset>
-      <fileset dir="${module.mercurial-server.basedir}/mercurial-server/src">
-        <patternset refid="compiler.resources"/>
-        <type type="file"/>
-      </fileset>
-    </copy>
-  </target>
-  
-  <target name="compile.module.mercurial-server.tests" depends="compile.module.mercurial-server.production" description="compile module mercurial-server; test classes" unless="skip.tests"/>
-  
-  <target name="clean.module.mercurial-server" description="cleanup module">
-    <delete dir="${mercurial-server.output.dir}"/>
-    <delete dir="${mercurial-server.testoutput.dir}"/>
-  </target>
-  
-  
-  <!-- Module mercurial-tests -->
-  
-  <dirname property="module.mercurial-tests.basedir" file="${ant.file}"/>
-  
-  
-  <property name="module.jdk.home.mercurial-tests" value="${project.jdk.home}"/>
-  <property name="module.jdk.bin.mercurial-tests" value="${project.jdk.bin}"/>
-  <property name="module.jdk.classpath.mercurial-tests" value="${project.jdk.classpath}"/>
-  
-  <property name="compiler.args.mercurial-tests" value="${compiler.args}"/>
-  
-  <property name="mercurial-tests.output.dir" value="${module.mercurial-tests.basedir}/mercurial-tests/classes"/>
-  <property name="mercurial-tests.testoutput.dir" value="${module.mercurial-tests.basedir}/mercurial-tests/classes"/>
-  
-  <path id="mercurial-tests.module.bootclasspath">
-    <!-- Paths to be included in compilation bootclasspath -->
-  </path>
-  
-  <path id="mercurial-tests.module.production.classpath">
-    <path refid="${module.jdk.classpath.mercurial-tests}"/>
-    <pathelement location="${mercurial-server.output.dir}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <path refid="library.junit.classpath"/>
-    <path refid="library.testng.classpath"/>
-    <path refid="library.jmock.classpath"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <pathelement location="${mercurial-agent.output.dir}"/>
-    <path refid="library.teamcity-testsapi.classpath"/>
-    <path refid="library.teamcity-impl.classpath"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-  </path>
-  
-  <path id="mercurial-tests.runtime.production.module.classpath">
-    <pathelement location="${mercurial-tests.output.dir}"/>
-    <pathelement location="${mercurial-server.output.dir}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.jdom.classpath"/>
-    <path refid="library.junit.classpath"/>
-    <path refid="library.testng.classpath"/>
-    <path refid="library.jmock.classpath"/>
-    <pathelement location="${mercurial-agent.output.dir}"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-    <path refid="library.teamcity-testsapi.classpath"/>
-    <path refid="library.teamcity-impl.classpath"/>
-  </path>
-  
-  <path id="mercurial-tests.module.classpath">
-    <path refid="${module.jdk.classpath.mercurial-tests}"/>
-    <pathelement location="${mercurial-tests.output.dir}"/>
-    <pathelement location="${mercurial-server.output.dir}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <path refid="library.junit.classpath"/>
-    <path refid="library.testng.classpath"/>
-    <path refid="library.jmock.classpath"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <pathelement location="${mercurial-agent.output.dir}"/>
-    <path refid="library.teamcity-testsapi.classpath"/>
-    <path refid="library.teamcity-impl.classpath"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-  </path>
-  
-  <path id="mercurial-tests.runtime.module.classpath">
-    <pathelement location="${mercurial-tests.output.dir}"/>
-    <pathelement location="${mercurial-server.output.dir}"/>
-    <path refid="library.teamcityapi-server.classpath"/>
-    <path refid="library.idea-openapi.classpath"/>
-    <path refid="library.log4j.classpath"/>
-    <pathelement location="${mercurial-common.output.dir}"/>
-    <path refid="library.teamcityapi-common.classpath"/>
-    <path refid="library.jdom.classpath"/>
-    <path refid="library.junit.classpath"/>
-    <path refid="library.testng.classpath"/>
-    <path refid="library.jmock.classpath"/>
-    <pathelement location="${mercurial-agent.output.dir}"/>
-    <path refid="library.teamcityapi-agent.classpath"/>
-    <path refid="library.teamcity-testsapi.classpath"/>
-    <path refid="library.teamcity-impl.classpath"/>
-  </path>
-  
-  
-  <patternset id="excluded.from.module.mercurial-tests">
-    <patternset refid="ignored.files"/>
-  </patternset>
-  
-  <patternset id="excluded.from.compilation.mercurial-tests">
-    <patternset refid="excluded.from.module.mercurial-tests"/>
-  </patternset>
-  
-  <path id="mercurial-tests.module.test.sourcepath">
-    <dirset dir="${module.mercurial-tests.basedir}/mercurial-tests">
-      <include name="src"/>
-    </dirset>
-  </path>
-  
-  
-  <target name="compile.module.mercurial-tests" depends="compile.module.mercurial-tests.production,compile.module.mercurial-tests.tests" description="Compile module mercurial-tests"/>
-  
-  <target name="compile.module.mercurial-tests.production" depends="compile.module.mercurial-server,compile.module.mercurial-common,compile.module.mercurial-agent" description="Compile module mercurial-tests; production classes"/>
-  
-  <target name="compile.module.mercurial-tests.tests" depends="compile.module.mercurial-tests.production" description="compile module mercurial-tests; test classes" unless="skip.tests">
-    <mkdir dir="${mercurial-tests.testoutput.dir}"/>
-    <javac destdir="${mercurial-tests.testoutput.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true" executable="${module.jdk.bin.mercurial-tests}/javac">
-      <compilerarg line="${compiler.args.mercurial-tests}"/>
-      <bootclasspath refid="mercurial-tests.module.bootclasspath"/>
-      <classpath refid="mercurial-tests.module.classpath"/>
-      <src refid="mercurial-tests.module.test.sourcepath"/>
-      <patternset refid="excluded.from.compilation.mercurial-tests"/>
-    </javac>
-    
-    <copy todir="${mercurial-tests.testoutput.dir}">
-      <fileset dir="${module.mercurial-tests.basedir}/mercurial-tests/src">
-        <patternset refid="compiler.resources"/>
-        <type type="file"/>
-      </fileset>
-    </copy>
-  </target>
-  
-  <target name="clean.module.mercurial-tests" description="cleanup module">
-    <delete dir="${mercurial-tests.output.dir}"/>
-    <delete dir="${mercurial-tests.testoutput.dir}"/>
-  </target>
-  
-  <target name="init" description="Build initialization">
-    <!-- Perform any build initialization in this target -->
-  </target>
-  
-  <target name="clean" depends="clean.module.main, clean.module.mercurial-common, clean.module.mercurial-agent, clean.module.mercurial-server, clean.module.mercurial-tests" description="cleanup all"/>
-  
-  <target name="build.modules" depends="init, clean, compile.module.main, compile.module.mercurial-common, compile.module.mercurial-agent, compile.module.mercurial-server, compile.module.mercurial-tests" description="build all modules"/>
-  
-  <target name="all" depends="build.modules" description="build all"/>
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="mercurial" default="all">
+  
+  
+  <property file="mercurial.properties"/>
+  <!-- Uncomment the following property if no tests compilation is needed -->
+  <!-- 
+  <property name="skip.tests" value="true"/>
+   -->
+  
+  <!-- Compiler options -->
+  
+  <property name="compiler.debug" value="on"/>
+  <property name="compiler.generate.no.warnings" value="off"/>
+  <property name="compiler.args" value=""/>
+  <property name="compiler.max.memory" value="128m"/>
+  <patternset id="ignored.files">
+    <exclude name="**/CVS/**"/>
+    <exclude name="**/SCCS/**"/>
+    <exclude name="**/RCS/**"/>
+    <exclude name="**/rcs/**"/>
+    <exclude name="**/.DS_Store/**"/>
+    <exclude name="**/.svn/**"/>
+    <exclude name="**/.pyc/**"/>
+    <exclude name="**/.pyo/**"/>
+    <exclude name="**/*.pyc/**"/>
+    <exclude name="**/*.pyo/**"/>
+    <exclude name="**/.git/**"/>
+    <exclude name="**/*.hprof/**"/>
+    <exclude name="**/_svn/**"/>
+    <exclude name="**/.hg/**"/>
+    <exclude name="**/*.lib/**"/>
+    <exclude name="**/*~/**"/>
+    <exclude name="**/__pycache__/**"/>
+    <exclude name="**/.bundle/**"/>
+    <exclude name="**/*.rbc/**"/>
+    <exclude name="**/*.orig/**"/>
+  </patternset>
+  <patternset id="library.patterns">
+    <include name="*.zip"/>
+    <include name="*.apk"/>
+    <include name="*.war"/>
+    <include name="*.egg"/>
+    <include name="*.ear"/>
+    <include name="*.ane"/>
+    <include name="*.swc"/>
+    <include name="*.jar"/>
+  </patternset>
+  <patternset id="compiler.resources">
+    <include name="**/?*.properties"/>
+    <include name="**/?*.xml"/>
+    <include name="**/?*.gif"/>
+    <include name="**/?*.png"/>
+    <include name="**/?*.jpeg"/>
+    <include name="**/?*.jpg"/>
+    <include name="**/?*.html"/>
+    <include name="**/?*.dtd"/>
+    <include name="**/?*.tld"/>
+    <include name="**/?*.jsp"/>
+    <include name="**/?*.tag"/>
+    <include name="**/?*.template"/>
+  </patternset>
+  
+  
+  <!-- Project Libraries -->
+  
+  <path id="library.idea-openapi.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/annotations.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/openapi.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/resources_en.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/util.jar"/>
+  </path>
+  
+  <path id="library.jdom.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/jdom.jar"/>
+  </path>
+  
+  <path id="library.jmock.classpath">
+    <pathelement location="${basedir}/mercurial-tests/lib/hamcrest-core-1.1.jar"/>
+    <pathelement location="${basedir}/mercurial-tests/lib/hamcrest-integration-1.1.jar"/>
+    <pathelement location="${basedir}/mercurial-tests/lib/hamcrest-library-1.1.jar"/>
+    <pathelement location="${basedir}/mercurial-tests/lib/jmock-2.5.1.jar"/>
+    <pathelement location="${basedir}/mercurial-tests/lib/jmock-SNAPSHOT.jar"/>
+  </path>
+  
+  <path id="library.junit.classpath">
+    <pathelement location="${basedir}/mercurial-tests/lib/junit-3.8.1.jar"/>
+  </path>
+  
+  <path id="library.log4j.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/log4j-1.2.12.jar"/>
+  </path>
+  
+  <path id="library.teamcity-impl.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/patches-impl.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/trove4j.jar"/>
+  </path>
+  
+  <path id="library.teamcity-testsapi.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/devPackage/tests/patches-test.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/devPackage/tests/tests-support.jar"/>
+  </path>
+  
+  <path id="library.teamcity_vcs_api.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/devPackage/server-common-api.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/devPackage/server-vcs-api.jar"/>
+  </path>
+  
+  <path id="library.teamcityapi-agent.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/buildAgent/lib/agent.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/devPackage/agent-api.jar"/>
+  </path>
+  
+  <path id="library.teamcityapi-common.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/devPackage/common-api.jar"/>
+  </path>
+  
+  <path id="library.teamcityapi-server.classpath">
+    <pathelement location="${path.variable.teamcitydistribution}/devPackage/server-api.jar"/>
+    <pathelement location="${path.variable.teamcitydistribution}/webapps/ROOT/WEB-INF/lib/server.jar"/>
+  </path>
+  
+  <path id="library.testng.classpath">
+    <pathelement location="${basedir}/mercurial-tests/lib/testng-5.7-jdk15.jar"/>
+  </path>
+  
+  
+  <!-- Application Server Libraries -->
+  
+  <!-- Modules -->
+  
+  
+  <!-- Module main -->
+  
+  <dirname property="module.main.basedir" file="${ant.file}"/>
+  
+  
+  
+  <property name="compiler.args.main" value="${compiler.args}"/>
+  
+  <property name="main.output.dir" value="undefined"/>
+  <property name="main.testoutput.dir" value="undefined"/>
+  
+  <path id="main.module.bootclasspath">
+    <!-- Paths to be included in compilation bootclasspath -->
+  </path>
+  
+  <path id="main.module.production.classpath"/>
+  
+  <path id="main.runtime.production.module.classpath"/>
+  
+  <path id="main.module.classpath"/>
+  
+  <path id="main.runtime.module.classpath"/>
+  
+  
+  <patternset id="excluded.from.module.main">
+    <patternset refid="ignored.files"/>
+  </patternset>
+  
+  <patternset id="excluded.from.compilation.main">
+    <patternset refid="excluded.from.module.main"/>
+  </patternset>
+  
+  
+  <target name="compile.module.main" depends="compile.module.main.production,compile.module.main.tests" description="Compile module main"/>
+  
+  <target name="compile.module.main.production" description="Compile module main; production classes"/>
+  
+  <target name="compile.module.main.tests" depends="compile.module.main.production" description="compile module main; test classes" unless="skip.tests"/>
+  
+  <target name="clean.module.main" description="cleanup module">
+    <delete dir="${main.output.dir}"/>
+    <delete dir="${main.testoutput.dir}"/>
+  </target>
+  
+  
+  <!-- Module mercurial-common -->
+  
+  <dirname property="module.mercurial-common.basedir" file="${ant.file}"/>
+  
+  
+  
+  <property name="compiler.args.mercurial-common" value="${compiler.args}"/>
+  
+  <property name="mercurial-common.output.dir" value="${module.mercurial-common.basedir}/mercurial-common/classes"/>
+  <property name="mercurial-common.testoutput.dir" value="${module.mercurial-common.basedir}/mercurial-common/classes"/>
+  
+  <path id="mercurial-common.module.bootclasspath">
+    <!-- Paths to be included in compilation bootclasspath -->
+  </path>
+  
+  <path id="mercurial-common.module.production.classpath">
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.jdom.classpath"/>
+  </path>
+  
+  <path id="mercurial-common.runtime.production.module.classpath">
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.jdom.classpath"/>
+  </path>
+  
+  <path id="mercurial-common.module.classpath">
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.jdom.classpath"/>
+  </path>
+  
+  <path id="mercurial-common.runtime.module.classpath">
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.jdom.classpath"/>
+  </path>
+  
+  
+  <patternset id="excluded.from.module.mercurial-common">
+    <patternset refid="ignored.files"/>
+  </patternset>
+  
+  <patternset id="excluded.from.compilation.mercurial-common">
+    <patternset refid="excluded.from.module.mercurial-common"/>
+  </patternset>
+  
+  <path id="mercurial-common.module.sourcepath">
+    <dirset dir="${module.mercurial-common.basedir}/mercurial-common">
+      <include name="src"/>
+    </dirset>
+  </path>
+  
+  
+  <target name="compile.module.mercurial-common" depends="compile.module.mercurial-common.production,compile.module.mercurial-common.tests" description="Compile module mercurial-common"/>
+  
+  <target name="compile.module.mercurial-common.production" description="Compile module mercurial-common; production classes">
+    <mkdir dir="${mercurial-common.output.dir}"/>
+    <javac destdir="${mercurial-common.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true">
+      <compilerarg line="${compiler.args.mercurial-common}"/>
+      <bootclasspath refid="mercurial-common.module.bootclasspath"/>
+      <classpath refid="mercurial-common.module.production.classpath"/>
+      <src refid="mercurial-common.module.sourcepath"/>
+      <patternset refid="excluded.from.compilation.mercurial-common"/>
+    </javac>
+    
+    <copy todir="${mercurial-common.output.dir}">
+      <fileset dir="${module.mercurial-common.basedir}/mercurial-common/src">
+        <patternset refid="compiler.resources"/>
+        <type type="file"/>
+      </fileset>
+    </copy>
+  </target>
+  
+  <target name="compile.module.mercurial-common.tests" depends="compile.module.mercurial-common.production" description="compile module mercurial-common; test classes" unless="skip.tests"/>
+  
+  <target name="clean.module.mercurial-common" description="cleanup module">
+    <delete dir="${mercurial-common.output.dir}"/>
+    <delete dir="${mercurial-common.testoutput.dir}"/>
+  </target>
+  
+  
+  <!-- Module mercurial-agent -->
+  
+  <dirname property="module.mercurial-agent.basedir" file="${ant.file}"/>
+  
+  
+  
+  <property name="compiler.args.mercurial-agent" value="${compiler.args}"/>
+  
+  <property name="mercurial-agent.output.dir" value="${module.mercurial-agent.basedir}/mercurial-agent/classes"/>
+  <property name="mercurial-agent.testoutput.dir" value="${module.mercurial-agent.basedir}/mercurial-agent/classes"/>
+  
+  <path id="mercurial-agent.module.bootclasspath">
+    <!-- Paths to be included in compilation bootclasspath -->
+  </path>
+  
+  <path id="mercurial-agent.module.production.classpath">
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+  </path>
+  
+  <path id="mercurial-agent.runtime.production.module.classpath">
+    <pathelement location="${mercurial-agent.output.dir}"/>
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.jdom.classpath"/>
+  </path>
+  
+  <path id="mercurial-agent.module.classpath">
+    <pathelement location="${mercurial-agent.output.dir}"/>
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+  </path>
+  
+  <path id="mercurial-agent.runtime.module.classpath">
+    <pathelement location="${mercurial-agent.output.dir}"/>
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.jdom.classpath"/>
+  </path>
+  
+  
+  <patternset id="excluded.from.module.mercurial-agent">
+    <patternset refid="ignored.files"/>
+  </patternset>
+  
+  <patternset id="excluded.from.compilation.mercurial-agent">
+    <patternset refid="excluded.from.module.mercurial-agent"/>
+  </patternset>
+  
+  <path id="mercurial-agent.module.sourcepath">
+    <dirset dir="${module.mercurial-agent.basedir}/mercurial-agent">
+      <include name="src"/>
+    </dirset>
+  </path>
+  
+  
+  <target name="compile.module.mercurial-agent" depends="compile.module.mercurial-agent.production,compile.module.mercurial-agent.tests" description="Compile module mercurial-agent"/>
+  
+  <target name="compile.module.mercurial-agent.production" depends="compile.module.mercurial-common" description="Compile module mercurial-agent; production classes">
+    <mkdir dir="${mercurial-agent.output.dir}"/>
+    <javac destdir="${mercurial-agent.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true">
+      <compilerarg line="${compiler.args.mercurial-agent}"/>
+      <bootclasspath refid="mercurial-agent.module.bootclasspath"/>
+      <classpath refid="mercurial-agent.module.production.classpath"/>
+      <src refid="mercurial-agent.module.sourcepath"/>
+      <patternset refid="excluded.from.compilation.mercurial-agent"/>
+    </javac>
+    
+    <copy todir="${mercurial-agent.output.dir}">
+      <fileset dir="${module.mercurial-agent.basedir}/mercurial-agent/src">
+        <patternset refid="compiler.resources"/>
+        <type type="file"/>
+      </fileset>
+    </copy>
+  </target>
+  
+  <target name="compile.module.mercurial-agent.tests" depends="compile.module.mercurial-agent.production" description="compile module mercurial-agent; test classes" unless="skip.tests"/>
+  
+  <target name="clean.module.mercurial-agent" description="cleanup module">
+    <delete dir="${mercurial-agent.output.dir}"/>
+    <delete dir="${mercurial-agent.testoutput.dir}"/>
+  </target>
+  
+  
+  <!-- Module mercurial-server -->
+  
+  <dirname property="module.mercurial-server.basedir" file="${ant.file}"/>
+  
+  
+  
+  <property name="compiler.args.mercurial-server" value="${compiler.args}"/>
+  
+  <property name="mercurial-server.output.dir" value="${module.mercurial-server.basedir}/mercurial-server/classes"/>
+  <property name="mercurial-server.testoutput.dir" value="${module.mercurial-server.basedir}/mercurial-server/classes"/>
+  
+  <path id="mercurial-server.module.bootclasspath">
+    <!-- Paths to be included in compilation bootclasspath -->
+  </path>
+  
+  <path id="mercurial-server.module.production.classpath">
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+  </path>
+  
+  <path id="mercurial-server.runtime.production.module.classpath">
+    <pathelement location="${mercurial-server.output.dir}"/>
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.jdom.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+  </path>
+  
+  <path id="mercurial-server.module.classpath">
+    <pathelement location="${mercurial-server.output.dir}"/>
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+  </path>
+  
+  <path id="mercurial-server.runtime.module.classpath">
+    <pathelement location="${mercurial-server.output.dir}"/>
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.jdom.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+  </path>
+  
+  
+  <patternset id="excluded.from.module.mercurial-server">
+    <patternset refid="ignored.files"/>
+  </patternset>
+  
+  <patternset id="excluded.from.compilation.mercurial-server">
+    <patternset refid="excluded.from.module.mercurial-server"/>
+  </patternset>
+  
+  <path id="mercurial-server.module.sourcepath">
+    <dirset dir="${module.mercurial-server.basedir}/mercurial-server">
+      <include name="resources"/>
+      <include name="src"/>
+    </dirset>
+  </path>
+  
+  
+  <target name="compile.module.mercurial-server" depends="compile.module.mercurial-server.production,compile.module.mercurial-server.tests" description="Compile module mercurial-server"/>
+  
+  <target name="compile.module.mercurial-server.production" depends="compile.module.mercurial-common" description="Compile module mercurial-server; production classes">
+    <mkdir dir="${mercurial-server.output.dir}"/>
+    <javac destdir="${mercurial-server.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true">
+      <compilerarg line="${compiler.args.mercurial-server}"/>
+      <bootclasspath refid="mercurial-server.module.bootclasspath"/>
+      <classpath refid="mercurial-server.module.production.classpath"/>
+      <src refid="mercurial-server.module.sourcepath"/>
+      <patternset refid="excluded.from.compilation.mercurial-server"/>
+    </javac>
+    
+    <copy todir="${mercurial-server.output.dir}">
+      <fileset dir="${module.mercurial-server.basedir}/mercurial-server/resources">
+        <patternset refid="compiler.resources"/>
+        <type type="file"/>
+      </fileset>
+      <fileset dir="${module.mercurial-server.basedir}/mercurial-server/src">
+        <patternset refid="compiler.resources"/>
+        <type type="file"/>
+      </fileset>
+    </copy>
+  </target>
+  
+  <target name="compile.module.mercurial-server.tests" depends="compile.module.mercurial-server.production" description="compile module mercurial-server; test classes" unless="skip.tests"/>
+  
+  <target name="clean.module.mercurial-server" description="cleanup module">
+    <delete dir="${mercurial-server.output.dir}"/>
+    <delete dir="${mercurial-server.testoutput.dir}"/>
+  </target>
+  
+  
+  <!-- Module mercurial-tests -->
+  
+  <dirname property="module.mercurial-tests.basedir" file="${ant.file}"/>
+  
+  
+  
+  <property name="compiler.args.mercurial-tests" value="${compiler.args}"/>
+  
+  <property name="mercurial-tests.output.dir" value="${module.mercurial-tests.basedir}/mercurial-tests/classes"/>
+  <property name="mercurial-tests.testoutput.dir" value="${module.mercurial-tests.basedir}/mercurial-tests/classes"/>
+  
+  <path id="mercurial-tests.module.bootclasspath">
+    <!-- Paths to be included in compilation bootclasspath -->
+  </path>
+  
+  <path id="mercurial-tests.module.production.classpath">
+    <pathelement location="${mercurial-server.output.dir}"/>
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <path refid="library.junit.classpath"/>
+    <path refid="library.testng.classpath"/>
+    <path refid="library.jmock.classpath"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <pathelement location="${mercurial-agent.output.dir}"/>
+    <path refid="library.teamcity-testsapi.classpath"/>
+    <path refid="library.teamcity-impl.classpath"/>
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+  </path>
+  
+  <path id="mercurial-tests.runtime.production.module.classpath">
+    <pathelement location="${mercurial-tests.output.dir}"/>
+    <pathelement location="${mercurial-server.output.dir}"/>
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.jdom.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+    <path refid="library.junit.classpath"/>
+    <path refid="library.testng.classpath"/>
+    <path refid="library.jmock.classpath"/>
+    <pathelement location="${mercurial-agent.output.dir}"/>
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <path refid="library.teamcity-testsapi.classpath"/>
+    <path refid="library.teamcity-impl.classpath"/>
+  </path>
+  
+  <path id="mercurial-tests.module.classpath">
+    <pathelement location="${mercurial-tests.output.dir}"/>
+    <pathelement location="${mercurial-server.output.dir}"/>
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <path refid="library.junit.classpath"/>
+    <path refid="library.testng.classpath"/>
+    <path refid="library.jmock.classpath"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <pathelement location="${mercurial-agent.output.dir}"/>
+    <path refid="library.teamcity-testsapi.classpath"/>
+    <path refid="library.teamcity-impl.classpath"/>
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+  </path>
+  
+  <path id="mercurial-tests.runtime.module.classpath">
+    <pathelement location="${mercurial-tests.output.dir}"/>
+    <pathelement location="${mercurial-server.output.dir}"/>
+    <path refid="library.teamcityapi-server.classpath"/>
+    <path refid="library.idea-openapi.classpath"/>
+    <path refid="library.log4j.classpath"/>
+    <pathelement location="${mercurial-common.output.dir}"/>
+    <path refid="library.teamcityapi-common.classpath"/>
+    <path refid="library.jdom.classpath"/>
+    <path refid="library.teamcity_vcs_api.classpath"/>
+    <path refid="library.junit.classpath"/>
+    <path refid="library.testng.classpath"/>
+    <path refid="library.jmock.classpath"/>
+    <pathelement location="${mercurial-agent.output.dir}"/>
+    <path refid="library.teamcityapi-agent.classpath"/>
+    <path refid="library.teamcity-testsapi.classpath"/>
+    <path refid="library.teamcity-impl.classpath"/>
+  </path>
+  
+  
+  <patternset id="excluded.from.module.mercurial-tests">
+    <patternset refid="ignored.files"/>
+  </patternset>
+  
+  <patternset id="excluded.from.compilation.mercurial-tests">
+    <patternset refid="excluded.from.module.mercurial-tests"/>
+  </patternset>
+  
+  <path id="mercurial-tests.module.test.sourcepath">
+    <dirset dir="${module.mercurial-tests.basedir}/mercurial-tests">
+      <include name="src"/>
+    </dirset>
+  </path>
+  
+  
+  <target name="compile.module.mercurial-tests" depends="compile.module.mercurial-tests.production,compile.module.mercurial-tests.tests" description="Compile module mercurial-tests"/>
+  
+  <target name="compile.module.mercurial-tests.production" depends="compile.module.mercurial-server,compile.module.mercurial-common,compile.module.mercurial-agent" description="Compile module mercurial-tests; production classes"/>
+  
+  <target name="compile.module.mercurial-tests.tests" depends="compile.module.mercurial-tests.production" description="compile module mercurial-tests; test classes" unless="skip.tests">
+    <mkdir dir="${mercurial-tests.testoutput.dir}"/>
+    <javac destdir="${mercurial-tests.testoutput.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true">
+      <compilerarg line="${compiler.args.mercurial-tests}"/>
+      <bootclasspath refid="mercurial-tests.module.bootclasspath"/>
+      <classpath refid="mercurial-tests.module.classpath"/>
+      <src refid="mercurial-tests.module.test.sourcepath"/>
+      <patternset refid="excluded.from.compilation.mercurial-tests"/>
+    </javac>
+    
+    <copy todir="${mercurial-tests.testoutput.dir}">
+      <fileset dir="${module.mercurial-tests.basedir}/mercurial-tests/src">
+        <patternset refid="compiler.resources"/>
+        <type type="file"/>
+      </fileset>
+    </copy>
+  </target>
+  
+  <target name="clean.module.mercurial-tests" description="cleanup module">
+    <delete dir="${mercurial-tests.output.dir}"/>
+    <delete dir="${mercurial-tests.testoutput.dir}"/>
+  </target>
+  
+  <target name="init" description="Build initialization">
+    <!-- Perform any build initialization in this target -->
+  </target>
+  
+  <target name="clean" depends="clean.module.main, clean.module.mercurial-common, clean.module.mercurial-agent, clean.module.mercurial-server, clean.module.mercurial-tests" description="cleanup all"/>
+  
+  <target name="build.modules" depends="init, clean, compile.module.main, compile.module.mercurial-common, compile.module.mercurial-agent, compile.module.mercurial-server, compile.module.mercurial-tests" description="build all modules"/>
+  
+  <target name="all" depends="build.modules" description="build all"/>
 </project>
\ No newline at end of file