changeset 92:dc26ddd9ffd4

changes from 5.0.x branch merged
author Pavel.Sher
date Wed, 09 Dec 2009 11:14:30 +0300
parents 0b93ba1c71e5 (current diff) 99fc78c3e8db (diff)
children a0aea01c32b0
files
diffstat 103 files changed, 2576 insertions(+), 483 deletions(-) [+]
line wrap: on
line diff
--- a/README.txt	Wed Nov 25 00:46:31 2009 +0300
+++ b/README.txt	Wed Dec 09 11:14:30 2009 +0300
@@ -3,10 +3,6 @@
 Installation
 =================================
 
-TeamCity 3.1.X
-
-Download mercurial-server.zip, extract jars and place them into the TeamCity/WEB-INF/lib directory. Restart server.
-
-TeamCity 4 EAP
+TeamCity 4.x/5.x
 
 Download mercurial-server.zip and put it into the .BuildServer/plugins folder. Restart server.
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSet.java	Wed Dec 09 11:14:30 2009 +0300
@@ -16,22 +16,24 @@
 package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
 
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
 
 /**
  * Represents Mercurial change set
  */
-public class ChangeSet {
-  private int myRevNumber;
-  @NotNull private String myId;
+public class ChangeSet extends ChangeSetRevision {
   @NotNull private String myUser;
   @NotNull private Date myTimestamp;
-  private String mySummary;
+  private String myDescription;
+  private boolean myContainsFiles;
+  private List<ChangeSetRevision> myParents;
 
   public ChangeSet(final int revNumber, @NotNull final String id) {
-    myRevNumber = revNumber;
-    myId = id;
+    super(revNumber, id);
   }
 
   /**
@@ -39,18 +41,7 @@
    * @param fullVersion full changeset version as reported by hg log command
    */
   public ChangeSet(@NotNull final String fullVersion) {
-    try {
-      int colon = fullVersion.indexOf(":");
-      if (colon != -1) {
-        myRevNumber = Integer.parseInt(fullVersion.substring(0, colon));
-        myId = fullVersion.substring(colon+1);
-      } else {
-        myRevNumber = -1;
-        myId = fullVersion;
-      }
-    } catch (Throwable e) {
-      throw new IllegalArgumentException(e);
-    }
+    super(fullVersion);
   }
 
   public void setUser(@NotNull final String user) {
@@ -61,34 +52,19 @@
     myTimestamp = timestamp;
   }
 
-  public void setSummary(final String summary) {
-    mySummary = summary;
-  }
-
-  /**
-   * Returns changeset revision id
-   * @return changeset revision id
-   */
-  @NotNull
-  public String getId() {
-    return myId;
+  public void setDescription(final String description) {
+    myDescription = description;
   }
 
-  /**
-   * Returns changeset revision number
-   * @return changeset revision number
-   */
-  public int getRevNumber() {
-    return myRevNumber;
+  public void setContainsFiles(final boolean containsFiles) {
+    myContainsFiles = containsFiles;
   }
 
-  /**
-   * Returns full changeset version as reported by hg log command: revnum:revid
-   * @return full changeset version as reported by hg log
-   */
-  @NotNull
-  public String getFullVersion() {
-    return myRevNumber + ":" + myId;
+  public void addParent(@NotNull ChangeSetRevision rev) {
+    if (myParents == null) {
+      myParents = new ArrayList<ChangeSetRevision>();
+    }
+    myParents.add(rev);
   }
 
   /**
@@ -113,7 +89,24 @@
    * Returns changeset summary specified by user
    * @return changeset summary
    */
-  public String getSummary() {
-    return mySummary;
+  public String getDescription() {
+    return myDescription;
+  }
+
+  /**
+   * Returns parrents of this change set, or null if there were no parents.
+   * @return see above
+   */
+  @Nullable
+  public List<ChangeSetRevision> getParents() {
+    return myParents;
+  }
+
+  /**
+   * Returns true if this change has changed files
+   * @return see above
+   */
+  public boolean containsFiles() {
+    return myContainsFiles;
   }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangeSetRevision.java	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,84 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Pavel.Sher
+ */
+public class ChangeSetRevision {
+  private final int myRevNumber;
+  @NotNull
+  private final String myId;
+
+  public ChangeSetRevision(final int revNumber, @NotNull final String id) {
+    myRevNumber = revNumber;
+    myId = id;
+  }
+
+  /**
+   * Constructor for version in the form revnum:changeset_id or just changeset_id (in this case rev number is set to -1)
+   * @param fullVersion full changeset version as reported by hg log command
+   */
+  public ChangeSetRevision(@NotNull final String fullVersion) {
+    try {
+      int colon = fullVersion.indexOf(":");
+      if (colon != -1) {
+        myRevNumber = Integer.parseInt(fullVersion.substring(0, colon));
+        myId = fullVersion.substring(colon+1);
+      } else {
+        myRevNumber = -1;
+        myId = fullVersion;
+      }
+    } catch (Throwable e) {
+      throw new IllegalArgumentException(e);
+    }
+  }
+
+  /**
+   * Returns changeset revision id
+   * @return changeset revision id
+   */
+  @NotNull
+  public String getId() {
+    return myId;
+  }
+
+  /**
+   * Returns changeset revision number
+   * @return changeset revision number
+   */
+  public int getRevNumber() {
+    return myRevNumber;
+  }
+
+  /**
+   * Returns full changeset version as reported by hg log command: revnum:revid
+   * @return full changeset version as reported by hg log
+   */
+  @NotNull
+  public String getFullVersion() {
+    return myRevNumber + ":" + myId;
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final ChangeSetRevision that = (ChangeSetRevision) o;
+
+    return myRevNumber == that.myRevNumber && myId.equals(that.myId);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myRevNumber;
+    result = 31 * result + myId.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "change:" + myId;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ChangedFilesCommand.java	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,61 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
+
+import com.intellij.execution.configurations.GeneralCommandLine;
+import jetbrains.buildServer.ExecResult;
+import jetbrains.buildServer.util.FileUtil;
+import jetbrains.buildServer.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Pavel.Sher
+ */
+public class ChangedFilesCommand extends BaseCommand {
+  private String myRevId;
+
+  public ChangedFilesCommand(@NotNull final Settings settings) {
+    super(settings);
+  }
+
+  public void setRevId(@NotNull final String revId) {
+    myRevId = revId;
+  }
+
+  public List<ModifiedFile> execute() throws VcsException {
+    File styleFile;
+    try {
+      styleFile = getStyleFile();
+    } catch (IOException e) {
+      throw new VcsException("Unable to create style file: " + e.toString(), e);
+    }
+    try {
+      GeneralCommandLine cli = createCommandLine();
+      cli.addParameter("log");
+      cli.addParameter("-r");
+      cli.addParameter(myRevId + ":" + myRevId);
+      cli.addParameter("--style=" + styleFile.getAbsolutePath());
+
+      ExecResult res = runCommand(cli);
+      return parseFiles(res.getStdout());
+    } finally {
+      FileUtil.delete(styleFile);
+    }
+  }
+
+  private File getStyleFile() throws IOException {
+    File styleFile = FileUtil.createTempFile("hg", "style");
+    FileUtil.writeFile(styleFile,
+            "changeset = \"{file_mods}{file_adds}{file_dels}\"\n" +
+            "file_add = \"A {file_add}\\n\"\n" +
+            "file_del = \"R {file_del}\\n\"\n" +
+            "file_mod = \"M {file_mod}\\n\"");
+    return styleFile;
+  }
+
+  private List<ModifiedFile> parseFiles(final String stdout) {
+    return StatusCommand.parseFiles(stdout);
+  }
+}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java	Wed Dec 09 11:14:30 2009 +0300
@@ -35,9 +35,11 @@
   private ArrayList<String> myPaths;
   private static final String CHANGESET_PREFIX = "changeset:";
   private static final String USER_PREFIX = "user:";
+  private static final String PARENT_PREFIX = "parent:";
   private static final String DATE_PREFIX = "date:";
   private static final String DATE_FORMAT = "EEE MMM d HH:mm:ss yyyy Z";
-  private static final String SUMMARY_PREFIX = "summary:";
+  private static final String DESCRIPTION_PREFIX = "description:";
+  private static final String FILES_PREFIX = "files:";
 
   public LogCommand(@NotNull Settings settings) {
     super(settings);
@@ -58,6 +60,7 @@
   public List<ChangeSet> execute() throws VcsException {
     GeneralCommandLine cli = createCommandLine();
     cli.addParameter("log");
+    cli.addParameter("-v");
     cli.addParameter("-b");
     cli.addParameter(getSettings().getBranchName());
     cli.addParameter("-r");
@@ -80,12 +83,20 @@
     List<ChangeSet> result = new ArrayList<ChangeSet>();
     String[] lines = stdout.split("\n");
     ChangeSet current = null;
-    int lineNum = 0;                  
+    int lineNum = 0;
+    boolean insideDescription = false;
+    StringBuilder descr = new StringBuilder();
     while (lineNum < lines.length) {
       String line = lines[lineNum];
       lineNum++;
 
       if (line.startsWith(CHANGESET_PREFIX)) {
+        insideDescription = false;
+        if (current != null) {
+          current.setDescription(descr.toString().trim());
+          descr.setLength(0);
+        }
+
         String revAndId = line.substring(CHANGESET_PREFIX.length()).trim();
         try {
           current = new ChangeSet(revAndId);
@@ -104,6 +115,17 @@
         continue;
       }
 
+      if (line.startsWith(FILES_PREFIX)) {
+        current.setContainsFiles(true);
+        continue;
+      }
+
+      if (line.startsWith(PARENT_PREFIX)) {
+        String parentRev = line.substring(PARENT_PREFIX.length()).trim();
+        current.addParent(new ChangeSetRevision(parentRev));
+        continue;
+      }
+
       if (line.startsWith(DATE_PREFIX)) {
         String date = line.substring(DATE_PREFIX.length()).trim();
         try {
@@ -117,12 +139,18 @@
         continue;
       }
 
-      if (line.startsWith(SUMMARY_PREFIX)) {
-        String summary = line.substring(SUMMARY_PREFIX.length()).trim();
-        current.setSummary(summary);
-
+      if (line.startsWith(DESCRIPTION_PREFIX)) {
+        insideDescription = true;
         continue;
       }
+
+      if (insideDescription) {
+        descr.append(line).append("\n");
+      }
+    }
+
+    if (insideDescription) {
+      current.setDescription(descr.toString().trim());
     }
 
     return result;
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/ModifiedFile.java	Wed Dec 09 11:14:30 2009 +0300
@@ -66,4 +66,21 @@
   public String getPath() {
     return myPath;
   }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    final ModifiedFile that = (ModifiedFile) o;
+
+    return myPath.equals(that.myPath) && myStatus == that.myStatus;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = myStatus.hashCode();
+    result = 31 * result + myPath.hashCode();
+    return result;
+  }
 }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/StatusCommand.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/StatusCommand.java	Wed Dec 09 11:14:30 2009 +0300
@@ -52,7 +52,7 @@
     return parseFiles(res.getStdout());
   }
 
-  private List<ModifiedFile> parseFiles(final String stdout) {
+  public static List<ModifiedFile> parseFiles(final String stdout) {
     List<ModifiedFile> result = new ArrayList<ModifiedFile>();
     String[] lines = stdout.split("\n");
     for (String line: lines) {
@@ -66,7 +66,7 @@
     return result;
   }
 
-  private ModifiedFile.Status toStatus(final char modifier) {
+  public static ModifiedFile.Status toStatus(final char modifier) {
     switch (modifier) {
       case 'A': return ModifiedFile.Status.ADDED;
       case 'M': return ModifiedFile.Status.MODIFIED;
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Wed Dec 09 11:14:30 2009 +0300
@@ -89,9 +89,9 @@
     List<ModificationData> result = new ArrayList<ModificationData>();
     Settings settings = createSettings(root);
     LogCommand lc = new LogCommand(settings);
-    String fromId = new ChangeSet(fromVersion).getId();
+    String fromId = new ChangeSetRevision(fromVersion).getId();
     lc.setFromRevId(fromId);
-    lc.setToRevId(new ChangeSet(currentVersion).getId());
+    lc.setToRevId(new ChangeSetRevision(currentVersion).getId());
     List<ChangeSet> changeSets = lc.execute();
     if (changeSets.isEmpty()) {
       return result;
@@ -100,18 +100,33 @@
     // invoke status command for each changeset and determine what files were modified in these changesets
     StatusCommand st = new StatusCommand(settings);
     ChangeSet prev = new ChangeSet(fromVersion);
-    for (int i=0; i<changeSets.size(); i++) {
-      ChangeSet cur = changeSets.get(i);
+    for (ChangeSet cur : changeSets) {
       if (cur.getId().equals(fromId)) continue; // skip already reported changeset
 
-      st.setFromRevId(prev.getId());
-      st.setToRevId(cur.getId());
-      List<ModifiedFile> modifiedFiles = st.execute();
+      String prevId = prev.getId();
+      List<ChangeSetRevision> curParents = cur.getParents();
+      boolean merge = curParents != null && curParents.size() > 1;
+      if (curParents != null && !merge) {
+        prevId = curParents.get(0).getId();
+      }
+
+      List<ModifiedFile> modifiedFiles = new ArrayList<ModifiedFile>();
+      if (merge) {
+        modifiedFiles.addAll(computeModifiedFilesForMergeCommit(settings, cur));
+      } else {
+        st.setFromRevId(prevId);
+        st.setToRevId(cur.getId());
+        modifiedFiles = st.execute();
+      }
+
       // changeset full version will be set into VcsChange structure and
       // stored in database (note that getContent method will be invoked with this version)
       List<VcsChange> files = toVcsChanges(modifiedFiles, prev.getFullVersion(), cur.getFullVersion(), includeRule);
-      if (files.isEmpty()) continue;
-      ModificationData md = new ModificationData(cur.getTimestamp(), files, cur.getSummary(), cur.getUser(), root, cur.getFullVersion(), cur.getId());
+      if (files.isEmpty() && !merge) continue;
+      ModificationData md = new ModificationData(cur.getTimestamp(), files, cur.getDescription(), cur.getUser(), root, cur.getFullVersion(), cur.getId());
+      if (merge) {
+        md.setCanBeIgnored(false);
+      }
       result.add(md);
       prev = cur;
     }
@@ -119,6 +134,14 @@
     return result;
   }
 
+  private Collection<ModifiedFile> computeModifiedFilesForMergeCommit(final Settings settings, final ChangeSet cur) throws VcsException {
+    if (!cur.containsFiles()) return Collections.emptyList();
+
+    ChangedFilesCommand cfc = new ChangedFilesCommand(settings);
+    cfc.setRevId(cur.getId());
+    return cfc.execute();
+  }
+
   private List<VcsChange> toVcsChanges(final List<ModifiedFile> modifiedFiles, String prevVer, String curVer, final IncludeRule includeRule) {
     List<VcsChange> files = new ArrayList<VcsChange>();
     for (ModifiedFile mf: modifiedFiles) {
@@ -145,17 +168,17 @@
   }
 
   @NotNull
-  public byte[] getContent(final VcsModification vcsModification,
-                           final VcsChangeInfo change,
-                           final VcsChangeInfo.ContentType contentType,
-                           final VcsRoot vcsRoot) throws VcsException {
+  public byte[] getContent(@NotNull final VcsModification vcsModification,
+                           @NotNull final VcsChangeInfo change,
+                           @NotNull final VcsChangeInfo.ContentType contentType,
+                           @NotNull final VcsRoot vcsRoot) throws VcsException {
     syncClonedRepository(vcsRoot);
     String version = contentType == VcsChangeInfo.ContentType.AFTER_CHANGE ? change.getAfterChangeRevisionNumber() : change.getBeforeChangeRevisionNumber();
     return getContent(change.getRelativeFileName(), vcsRoot, version);
   }
 
   @NotNull
-  public byte[] getContent(final String filePath, final VcsRoot vcsRoot, final String version) throws VcsException {
+  public byte[] getContent(@NotNull final String filePath, @NotNull final VcsRoot vcsRoot, @NotNull final String version) throws VcsException {
     syncClonedRepository(vcsRoot);
     Settings settings = createSettings(vcsRoot);
     CatCommand cc = new CatCommand(settings);
@@ -178,10 +201,12 @@
     return new byte[0];
   }
 
+  @NotNull
   public String getName() {
     return Constants.VCS_NAME;
   }
 
+  @NotNull
   @Used("jsp")
   public String getDisplayName() {
     return "Mercurial";
@@ -206,12 +231,13 @@
     };
   }
 
+  @NotNull
   public String getVcsSettingsJspFilePath() {
     return "mercurialSettings.jsp";
   }
 
   @NotNull
-  public String getCurrentVersion(final VcsRoot root) throws VcsException {
+  public String getCurrentVersion(@NotNull final VcsRoot root) throws VcsException {
     // we will return full version of the most recent change as current version
     syncClonedRepository(root);
     Settings settings = createSettings(root);
@@ -224,6 +250,7 @@
     return result.get(settings.getBranchName()).getFullVersion();
   }
 
+  @NotNull
   public String describeVcsRoot(final VcsRoot vcsRoot) {
     return "mercurial: " + vcsRoot.getProperty(Constants.REPOSITORY_PROP);
   }
@@ -233,7 +260,7 @@
   }
 
   @Nullable
-  public String testConnection(final VcsRoot vcsRoot) throws VcsException {
+  public String testConnection(@NotNull final VcsRoot vcsRoot) throws VcsException {
     Settings settings = createSettings(vcsRoot);
     IdentifyCommand id = new IdentifyCommand(settings);
     StringBuilder res = new StringBuilder();
@@ -261,7 +288,7 @@
     return defaults;
   }
 
-  public String getVersionDisplayName(final String version, final VcsRoot root) throws VcsException {
+  public String getVersionDisplayName(@NotNull final String version, @NotNull final VcsRoot root) throws VcsException {
     return new ChangeSet(version).getId();
   }
 
@@ -281,11 +308,11 @@
     };
   }
 
-  public void buildPatch(final VcsRoot root,
+  public void buildPatch(@NotNull final VcsRoot root,
                          @Nullable final String fromVersion,
                          @NotNull final String toVersion,
-                         final PatchBuilder builder,
-                         final CheckoutRules checkoutRules) throws IOException, VcsException {
+                         @NotNull final PatchBuilder builder,
+                         @NotNull final CheckoutRules checkoutRules) throws IOException, VcsException {
     syncClonedRepository(root);
     Settings settings = createSettings(root);
     if (fromVersion == null) {
@@ -430,7 +457,7 @@
   }
 
   @Override
-  public boolean ignoreServerCachesFor(final VcsRoot root) {
+  public boolean ignoreServerCachesFor(@NotNull final VcsRoot root) {
     // since a copy of repository for each VCS root is already stored on disk
     // we do not need separate cache for our patches 
     return true;
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java	Wed Dec 09 11:14:30 2009 +0300
@@ -34,11 +34,11 @@
   }
 
   public void checkout_on_agent() throws IOException, VcsException {
-    testUpdate(createVcsRoot(), "4:b06a290a363b", "cleanPatch1/after", new IncludeRule(".", ".", null));
+    testUpdate(createVcsRoot(simpleRepo()), "4:b06a290a363b", "cleanPatch1/after", new IncludeRule(".", ".", null));
   }
 
   public void checkout_on_agent_include_rule_with_mapping() throws IOException, VcsException {
-    testUpdate(createVcsRoot(), "4:b06a290a363b", "cleanPatch1/after", new IncludeRule("+:.", "subdir", null));
+    testUpdate(createVcsRoot(simpleRepo()), "4:b06a290a363b", "cleanPatch1/after", new IncludeRule("+:.", "subdir", null));
   }
 
   private void testUpdate(final VcsRoot vcsRoot, String version, String expected, final IncludeRule includeRule) throws VcsException, IOException {
@@ -62,11 +62,11 @@
   }
 
   public void checkout_on_agent_from_branch() throws IOException, VcsException {
-    testUpdate(createVcsRoot("test_branch"), "7:376dcf05cd2a", "patch3/after", new IncludeRule(".", ".", null));
+    testUpdate(createVcsRoot(simpleRepo(), "test_branch"), "7:376dcf05cd2a", "patch3/after", new IncludeRule(".", ".", null));
   }
 
   public void update_on_agent() throws IOException, VcsException {
-    VcsRoot vcsRoot = createVcsRoot();
+    VcsRoot vcsRoot = createVcsRoot(simpleRepo());
     doUpdate(vcsRoot, "3:9522278aa38d", new IncludeRule(".", ".", null));
     File workDir = doUpdate(vcsRoot, "4:b06a290a363b", new IncludeRule(".", ".", null));
 
@@ -74,7 +74,7 @@
   }
 
   public void update_on_agent_with_include_rule() throws IOException, VcsException {
-    VcsRoot vcsRoot = createVcsRoot();
+    VcsRoot vcsRoot = createVcsRoot(simpleRepo());
     doUpdate(vcsRoot, "3:9522278aa38d", new IncludeRule(".", "subdir", null));
     File workDir = doUpdate(vcsRoot, "4:b06a290a363b", new IncludeRule(".", "subdir", null));
 
@@ -82,7 +82,7 @@
   }
 
   public void update_on_agent_from_branch() throws IOException, VcsException {
-    VcsRoot vcsRoot = createVcsRoot("test_branch");
+    VcsRoot vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
     doUpdate(vcsRoot, "7:376dcf05cd2a", new IncludeRule(".", ".", null));
     File workDir = doUpdate(vcsRoot, "8:04c3ae4c6312", new IncludeRule(".", ".", null));
 
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialTestCase.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BaseMercurialTestCase.java	Wed Dec 09 11:14:30 2009 +0300
@@ -35,26 +35,25 @@
     myTempFiles.cleanup();
   }
 
-  protected VcsRootImpl createVcsRoot() throws IOException {
+  protected VcsRootImpl createVcsRoot(@NotNull String repPath) throws IOException {
     VcsRootImpl vcsRoot = new VcsRootImpl(1, Constants.VCS_NAME);
     vcsRoot.addProperty(Constants.HG_COMMAND_PATH_PROP, new File("mercurial-tests/testData/bin/hg.exe").getAbsolutePath());
-    String repPath = getRepositoryPath();
     File repository = LocalRepositoryUtil.prepareRepository(repPath);
     vcsRoot.addProperty(Constants.REPOSITORY_PROP, repository.getAbsolutePath());
     return vcsRoot;
   }
 
-  protected VcsRootImpl createVcsRoot(@NotNull String branchName) throws IOException {
-    VcsRootImpl vcsRoot = createVcsRoot();
+  protected VcsRootImpl createVcsRoot(@NotNull String repPath, @NotNull String branchName) throws IOException {
+    VcsRootImpl vcsRoot = createVcsRoot(repPath);
     vcsRoot.addProperty(Constants.BRANCH_NAME_PROP, branchName);
     return vcsRoot;
   }
 
-  private String getRepositoryPath() {
-    return new File("mercurial-tests/testData/rep1").getAbsolutePath();
+  protected void cleanRepositoryAfterTest(@NotNull String repPath) {
+    LocalRepositoryUtil.forgetRepository(repPath);
   }
 
-  protected void cleanRepositoryAfterTest() {
-    LocalRepositoryUtil.forgetRepository(getRepositoryPath());
+  protected String simpleRepo() {
+    return new File("mercurial-tests/testData/rep1").getAbsolutePath();
   }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Wed Dec 09 11:14:30 2009 +0300
@@ -24,6 +24,7 @@
 import jetbrains.buildServer.vcs.*;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import jetbrains.buildServer.vcs.patches.PatchBuilderImpl;
+import junit.framework.Assert;
 import org.jmock.Mock;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -32,6 +33,8 @@
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -62,18 +65,18 @@
   }
 
   public void test_get_current_version() throws Exception {
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
-    assertEquals(myVcs.getCurrentVersion(vcsRoot), "6:b9deb9a1c6f4");
-    assertEquals("b9deb9a1c6f4", myVcs.getVersionDisplayName("6:b9deb9a1c6f4", vcsRoot));
+    assertEquals(myVcs.getCurrentVersion(vcsRoot), "10:9c6a6b4aede0");
+    assertEquals("9c6a6b4aede0", myVcs.getVersionDisplayName("10:9c6a6b4aede0", vcsRoot));
 
-    assertEquals(myVcs.getCurrentVersion(createVcsRoot("test_branch")), "8:04c3ae4c6312");
+    assertEquals(myVcs.getCurrentVersion(createVcsRoot(simpleRepo(), "test_branch")), "8:04c3ae4c6312");
 
-    assertEquals(myVcs.getCurrentVersion(createVcsRoot("name with space")), "9:9babcf2d5705");
+    assertEquals(myVcs.getCurrentVersion(createVcsRoot(simpleRepo(), "name with space")), "9:9babcf2d5705");
   }
 
   public void test_collect_changes() throws Exception {
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     List<ModificationData> changes = myVcs.collectBuildChanges(vcsRoot, "0:9875b412a788", "3:9522278aa38d", new CheckoutRules(""));
     assertEquals(3, changes.size());
@@ -104,7 +107,7 @@
   }
 
   public void test_collect_changes_with_checkout_rules() throws Exception {
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     List<ModificationData> changes = myVcs.collectBuildChanges(vcsRoot, "0:9875b412a788", "3:9522278aa38d", new CheckoutRules("-:.\n+:dir1/subdir"));
     assertEquals(changes.size(), 0);
@@ -118,7 +121,7 @@
   @Test
   public void test_build_patch() throws IOException, VcsException {
     setName("cleanPatch1");
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -139,7 +142,7 @@
 
   public void test_build_incremental_patch() throws IOException, VcsException {
     setName("patch1");
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -152,7 +155,7 @@
 
   public void test_build_incremental_patch_checkout_rules() throws IOException, VcsException {
     setName("patch1_checkout_rules");
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -165,7 +168,7 @@
 
   public void test_build_incremental_patch_file_with_space() throws IOException, VcsException {
     setName("patch2");
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -177,7 +180,7 @@
   }
 
   public void test_get_content() throws IOException, VcsException {
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     byte[] content = myVcs.getContent("dir1/subdir/file2.txt", vcsRoot, "4:b06a290a363b");
     assertEquals(new String(content), "bbb");
@@ -186,15 +189,14 @@
   }
 
   public void test_get_content_in_branch() throws IOException, VcsException {
-    VcsRootImpl vcsRoot = createVcsRoot("test_branch");
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
 
-    byte[] content = myVcs.getContent("file_in_branch.txt", vcsRoot, "7:376dcf05cd2a");
-    content = myVcs.getContent("file_in_branch.txt", vcsRoot, "8:04c3ae4c6312");
+    byte[] content = myVcs.getContent("file_in_branch.txt", vcsRoot, "8:04c3ae4c6312");
     assertEquals(new String(content), "file from the test_branch\r\nfile modified");
   }
 
   public void test_test_connection() throws IOException, VcsException {
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
     System.out.println(myVcs.testConnection(vcsRoot));
 
@@ -207,8 +209,8 @@
   }
 
   public void test_tag() throws IOException, VcsException {
-    VcsRootImpl vcsRoot = createVcsRoot();
-    cleanRepositoryAfterTest(); 
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
+    cleanRepositoryAfterTest(simpleRepo());
 
     String actualTag = myVcs.label("new:tag", "1:1d446e82d356", vcsRoot, new CheckoutRules(""));
     assertEquals(actualTag, "new_tag");
@@ -224,8 +226,8 @@
   }
 
   public void test_tag_in_branch() throws IOException, VcsException {
-    VcsRootImpl vcsRoot = createVcsRoot("test_branch");
-    cleanRepositoryAfterTest();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
+    cleanRepositoryAfterTest(simpleRepo());
 
     String actualTag = myVcs.label("branch_tag", "7:376dcf05cd2a", vcsRoot, new CheckoutRules(""));
     assertEquals(actualTag, "branch_tag");
@@ -241,7 +243,7 @@
   }
 
   public void test_collect_changes_in_branch() throws Exception {
-    VcsRootImpl vcsRoot = createVcsRoot("test_branch");
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
 
     // fromVersion(6:b9deb9a1c6f4) is not in the branch (it is in the default branch)
     List<ModificationData> changes = myVcs.collectBuildChanges(vcsRoot, "6:b9deb9a1c6f4", "7:376dcf05cd2a", new CheckoutRules(""));
@@ -263,9 +265,18 @@
     assertEquals(md1.getDescription(), "file modified");
   }
 
+  public void test_collect_changes_after_merge() throws IOException, VcsException {
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
+
+    List<ModificationData> changes = myVcs.collectBuildChanges(vcsRoot, "6:b9deb9a1c6f4", "12:1870e1100fab", new CheckoutRules(""));
+    for (ModificationData md: changes) {
+      System.out.println(md);
+    }
+  }
+
   public void test_full_patch_from_branch() throws IOException, VcsException {
     setName("patch3");
-    VcsRootImpl vcsRoot = createVcsRoot("test_branch");
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -278,7 +289,7 @@
 
   public void test_full_patch_from_branch_with_checkout_rules() throws IOException, VcsException {
     setName("patch3_checkout_rules1");
-    VcsRootImpl vcsRoot = createVcsRoot("test_branch");
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -291,7 +302,7 @@
 
   public void test_full_patch_from_branch_with_checkout_rules_mapped_and_skipped() throws IOException, VcsException {
     setName("patch3_checkout_rules2");
-    VcsRootImpl vcsRoot = createVcsRoot("test_branch");
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -304,7 +315,7 @@
 
   public void test_incremental_patch_from_branch() throws IOException, VcsException {
     setName("patch4");
-    VcsRootImpl vcsRoot = createVcsRoot("test_branch");
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo(), "test_branch");
 
     final ByteArrayOutputStream output = new ByteArrayOutputStream();
     final PatchBuilderImpl builder = new PatchBuilderImpl(output);
@@ -317,7 +328,7 @@
 
   @Test(enabled = false)
   public void support_anchor_branch_notation() throws IOException {
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
     String repPath = vcsRoot.getProperty(Constants.REPOSITORY_PROP);
     vcsRoot.addProperty(Constants.REPOSITORY_PROP, repPath + "#test_branch");
     Settings settings = new Settings(new File(myServerPaths.getCachesDir()), vcsRoot);
@@ -334,7 +345,7 @@
 
   public void build_patch_using_custom_clone_path() throws IOException, VcsException {
     setName("cleanPatch1");
-    VcsRootImpl vcsRoot = createVcsRoot();
+    VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
     File cloneDir = myTempFiles.createTempDir();
     vcsRoot.addProperty(Constants.SERVER_CLONE_PATH_PROP, cloneDir.getAbsolutePath());
 
@@ -349,6 +360,65 @@
     assertTrue(new File(cloneDir, new File(vcsRoot.getProperty(Constants.REPOSITORY_PROP)).getName()).isDirectory());
   }
 
+  private String mergeCommittsRepo() {
+    return new File("mercurial-tests/testData/rep2").getAbsolutePath();
+  }
+
+  public void test_collect_changes_merge() throws Exception {
+    VcsRootImpl vcsRoot = createVcsRoot(mergeCommittsRepo());
+
+    List<ModificationData> changes = myVcs.collectBuildChanges(vcsRoot, "1:a3d15477d297", "4:6eeb8974fe67", new CheckoutRules(""));
+    assertEquals(changes.size(), 3);
+
+    assertEquals("2:db8a04d262f3", changes.get(0).getVersion());
+    assertEquals("3:2538c02bafeb", changes.get(1).getVersion());
+    assertEquals("4:6eeb8974fe67", changes.get(2).getVersion());
+
+    assertFiles(Arrays.asList("A dir1/file1.txt"), changes.get(0));
+    assertFiles(Arrays.asList("A dir2/file2.txt"), changes.get(1));
+    Assert.assertEquals(changes.get(2).getChanges().toString(), 0, changes.get(2).getChangeCount());
+  }
+
+  public void test_collect_changes_merge_conflict() throws Exception {
+    VcsRootImpl vcsRoot = createVcsRoot(mergeCommittsRepo());
+
+    List<ModificationData> changes = myVcs.collectBuildChanges(vcsRoot, "6:6066b677d026", "8:b6e2d176fe8e", new CheckoutRules(""));
+    assertEquals(changes.size(), 2);
+
+    assertFiles(Arrays.asList("A dir4/file41.txt"), changes.get(0));
+    assertFiles(Arrays.asList("M dir4/file41.txt", "A dir4/file42.txt", "A dir4/file43.txt", "R dir3/file3.txt"), changes.get(1));
+  }
+
+  public void test_collect_changes_merge_conflict_named_branch() throws Exception {
+    VcsRootImpl vcsRoot = createVcsRoot(mergeCommittsRepo());
+
+    List<ModificationData> changes = myVcs.collectBuildChanges(vcsRoot, "8:b6e2d176fe8e", "12:1e620196c4b6", new CheckoutRules(""));
+    assertEquals(changes.size(), 2);
+
+    assertFiles(Arrays.asList("A dir6/file6.txt"), changes.get(0));
+    assertFiles(Arrays.asList("M dir6/file6.txt", "A dir5/file5.txt"), changes.get(1));
+  }
+
+  private void assertFiles(final List<String> expectedFiles, final ModificationData modificationData) {
+    List<String> actualFiles = new ArrayList<String>();
+    for (VcsChange vc: modificationData.getChanges()) {
+      actualFiles.add(toFileStatus(vc.getType()) + " " + vc.getRelativeFileName());
+    }
+    Assert.assertEquals("Actual files: " + actualFiles.toString(), expectedFiles, actualFiles);
+  }
+
+  private String toFileStatus(VcsChange.Type type) {
+    switch (type) {
+      case ADDED:
+        return "A";
+      case REMOVED:
+        return "R";
+      case CHANGED:
+        return "M";
+    }
+    return "?";
+  }
+
   private Object normalizePath(final String path) {
     return path.replace(File.separatorChar, '/');
   }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommandTest.java	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommandTest.java	Wed Dec 09 11:14:30 2009 +0300
@@ -17,6 +17,7 @@
 
 import jetbrains.buildServer.vcs.VcsException;
 import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import java.io.IOException;
@@ -24,8 +25,14 @@
 
 @Test
 public class LogCommandTest extends BaseCommandTestCase {
+  @BeforeMethod
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    setRepository("mercurial-tests/testData/rep1", true);
+  }
+
   public void testOneChangeSet() throws Exception {
-    setRepository("mercurial-tests/testData/rep1", true);
     final String toId = "9875b412a788";
     List<ChangeSet> changes = runLog(null, toId);
     assertEquals(1, changes.size());
@@ -33,11 +40,11 @@
     assertEquals(0, changeSet.getRevNumber());
     assertEquals(toId, changeSet.getId());
     assertEquals("pavel@localhost", changeSet.getUser());
-    assertEquals("dir1 created", changeSet.getSummary());
+    assertEquals("dir1 created", changeSet.getDescription());
+    assertNull(changeSet.getParents());
   }
 
   public void testMoreThanOneChangeSet() throws Exception {
-    setRepository("mercurial-tests/testData/rep1", true);
     final String fromId = "9875b412a788";
     final String toId = "7209b1f1d793";
     List<ChangeSet> changes = runLog(fromId, toId);
@@ -45,14 +52,35 @@
     ChangeSet changeSet1 = changes.get(0);
     final ChangeSet changeSet2 = changes.get(1);
     final ChangeSet changeSet3 = changes.get(2);
-    assertEquals("dir1 created", changeSet1.getSummary());
-    assertEquals("new file added", changeSet2.getSummary());
-    assertEquals("file4.txt added", changeSet3.getSummary());
+    assertEquals("dir1 created", changeSet1.getDescription());
+    assertEquals("new file added", changeSet2.getDescription());
+    assertEquals("file4.txt added", changeSet3.getDescription());
 
     changes = runLog(null, toId);
     assertEquals(3, changes.size());
     changeSet1 = changes.get(2);
-    assertEquals("file4.txt added", changeSet1.getSummary());
+    assertEquals("file4.txt added", changeSet1.getDescription());
+  }
+
+  public void changeset_parents() throws VcsException, IOException {
+    setRepository("mercurial-tests/testData/rep2", true);
+    List<ChangeSet> changes = runLog("6eeb8974fe67", "6eeb8974fe67");
+    assertEquals(1, changes.size());
+    ChangeSet cs = changes.get(0);
+    assertNotNull(cs.getParents());
+    assertEquals(2, cs.getParents().size());
+    assertTrue(cs.getParents().contains(new ChangeSetRevision("1:a3d15477d297")));
+    assertTrue(cs.getParents().contains(new ChangeSetRevision("3:2538c02bafeb")));
+  }
+
+  public void parse_multiline_description() throws VcsException, IOException {
+    List<ChangeSet> changes = runLog("9babcf2d5705", "9c6a6b4aede0");
+    assertEquals(1, changes.size());
+    assertEquals("Multiline description\n" +
+            "description with new\n" +
+            "lines\n" +
+            "aaaa\n" +
+            "bbb", changes.get(0).getDescription());
   }
 
   private List<ChangeSet> runLog(final String fromId, final String toId) throws IOException, VcsException {
--- a/mercurial-tests/testData/bin/Mercurial.ini	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Mercurial.ini	Wed Dec 09 11:14:30 2009 +0300
@@ -1,17 +1,71 @@
-; System-wide Mercurial config file.  To override these settings on a
-; per-user basis, please edit the following file instead, where
-; USERNAME is your Windows user name:
-;   C:\Documents and Settings\USERNAME\Mercurial.ini
+; System-wide Mercurial config file.
+;
+; !!!  Do Not Edit This File !!!
+;
+; This file will be replaced by the installer on every upgrade.
+; Editing this file can cause strange side effects on Vista.
+;
+; http://bitbucket.org/tortoisehg/stable/issue/135
+;
+; To change settings you see in this file, override (or enable) them in
+; your user Mercurial.ini file, where USERNAME is your Windows user name:
+;
+; XP or older    - C:\Documents and Settings\USERNAME\Mercurial.ini
+; Vista or later - C:\Users\USERNAME\Mercurial.ini
+
 
 [ui]
+; editor used to enter commit logs, etc.  Most text editors will work.
 editor = notepad
+; show changed files and be a bit more verbose if True
+; verbose = True
+ 
+; username data to appear in commits
+; it usually takes the form: Joe User <joe.user@host.com>
+; username = Joe User <j.user@example.com>
 
+; In order to push/pull over ssh you must specify an ssh tool
+;ssh = "C:\Progra~1\TortoiseSVN\bin\TortoisePlink.exe" -ssh -2
+;ssh = C:\cygwin\bin\ssh
+
+;
+; For more information about mercurial extensions, start here
+; http://www.selenic.com/mercurial/wiki/index.cgi/UsingExtensions
+;
+; Extensions shipped with Mercurial
+;
 [extensions]
-; The win32text extension is available and installed by default.  It
-; provides built-in Python hooks to perform line ending conversions.
-; This is normally much faster than running an external program.
-hgext.win32text =
+;acl =
+;alias =
+;bookmarks =
+;bugzilla =
+;children =
+;churn =
+;color =
+;convert =
+;extdiff =
+;fetch =
+;gpg =
+;graphlog = 
+;hgcia =
+;hgk =
+;highlight = 
+;interhg =
+;keyword =
+;mq =
+;notify =
+;pager =
+;parentrevspec =
+;patchbomb =
+;purge =
+;rebase =
+;record =
+;transplant =
+;win32mbcs =
+;win32text =
+;zeroconf =
 
+; To use cleverencode/cleverdecode, you must enable win32text extension
 
 [encode]
 ; Encode files that don't contain NUL characters.
@@ -34,11 +88,43 @@
 
 ; **.txt = dumbdecode:
 
+[patch]
+; If you enable win32text filtering, you will want to enable this
+; line as well to allow patching to work correctly.
+
+; eol = crlf
+
+
+;
+; Define external diff commands
+;
+[extdiff]
+;cmd.bc3diff = C:\Program Files\Beyond Compare 3\BCompare.exe
+;cmd.vdiff = C:\Progra~1\TortoiseSVN\bin\TortoiseMerge.exe
+;cmd.vimdiff = gvim.exe
+;opts.vimdiff = -f '+next' '+execute "DirDiff ".argv(0)." ".argv(1)'
+
+
+[hgk]
+; Replace the following with your path to hgk, uncomment it and 
+; install ActiveTcl (or another win32 port like tclkit)
+; path="C:\Program Files\Mercurial\Contrib\hgk.tcl"
+; vdiff=vdiff
+ 
+
+;
+; The git extended diff format can represent binary files, file
+; permission changes, and rename information that the normal patch format
+; cannot describe.  However it is also not compatible with tools which
+; expect normal patches. so enable git patches at your own risk.
+;
+[diff]
+;git = false
+;nodates = false
+
 # Some default global settings for common merge tools
 
 [merge-tools]
-# Some default global settings for common merge tools
-
 kdiff3.args=--auto --L1 base --L2 local --L3 other $base $local $other -o $output
 kdiff3.regkey=Software\KDiff3
 kdiff3.regappend=\kdiff3.exe
@@ -76,13 +162,26 @@
 p4merge.gui=True
 p4merge.priority=-8
 
-tortoisemerge.args=/base: $output /mine:$local /theirs:$other /merged:$output
+tortoisemerge.args=/base:$base /mine:$local /theirs:$other /merged:$output
 tortoisemerge.regkey=Software\TortoiseSVN
+tortoisemerge.checkchanged=True
 tortoisemerge.gui=True
 
 ecmerge.args=$base $local $other --mode=merge3 --title0=base --title1=local --title2=other --to=$output
 ecmerge.regkey=Software\Elli\xc3\xa9 Computing\Merge
 ecmerge.gui=True
 
+filemerge.executable=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge
 filemerge.args=-left $other -right $local -ancestor $base -merge $output
 filemerge.gui=True
+
+beyondcompare3.args=$local $other $base $output /ro /lefttitle=local /centertitle=base /righttitle=other /automerge /reviewconflicts /solo
+beyondcompare3.regkey=Software\Scooter Software\Beyond Compare 3
+beyondcompare3.regname=ExePath
+beyondcompare3.gui=True
+
+winmerge.args=/e /u /dl local /dr other /wr $local $other $output
+winmerge.regkey=Software\Thingamahoochie\WinMerge
+winmerge.regname=Executable
+winmerge.checkchanged=True
+winmerge.gui=True
--- a/mercurial-tests/testData/bin/Mercurial.url	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Mercurial.url	Wed Dec 09 11:14:30 2009 +0300
@@ -1,2 +1,2 @@
 [InternetShortcut]
-URL=http://www.selenic.com/mercurial/
+URL=http://mercurial.selenic.com/
--- a/mercurial-tests/testData/bin/ReadMe.html	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/ReadMe.html	Wed Dec 09 11:14:30 2009 +0300
@@ -5,9 +5,25 @@
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
     <style type="text/css">
       <!--
-      .indented
-      {
-      padding-left: 10pt;
+      html {
+        font-family: sans-serif;
+        margin: 1em 2em;
+      }
+
+      p {
+        margin-top: 0.5em;
+        margin-bottom: 0.5em;
+      }
+
+      pre {
+        margin: 0.25em 0em;
+        padding: 0.5em;
+        background-color: #EEE;
+        border: thin solid #CCC;
+      }
+
+      .indented {
+        padding-left: 10pt;
       }
       -->
     </style>
@@ -18,95 +34,130 @@
 
     <p>Welcome to Mercurial for Windows!</p>
 
-    <p>Mercurial is a command-line application.  You must run it from
+    <p>
+      Mercurial is a command-line application. You must run it from
       the Windows command prompt (or if you're hard core, a <a
-      href="http://www.mingw.org/">MinGW</a> shell).</p>
+      href="http://www.mingw.org/">MinGW</a> shell).
+    </p>
 
-    <p><div class="indented"><i>Note: the standard <a
-      href="http://www.mingw.org/">MinGW</a> msys startup script uses
-      rxvt which has problems setting up standard input and output.
-      Running bash directly works correctly.</i></div>
+    <p class="indented">
+      <i>Note: the standard <a href="http://www.mingw.org/">MinGW</a>
+      msys startup script uses rxvt which has problems setting up
+      standard input and output. Running bash directly works
+      correctly.</i>
+    </p>
 
-    <p>For documentation, please visit the <a
-      href="http://www.selenic.com/mercurial">Mercurial web site</a>.
+    <p>
+      For documentation, please visit the <a
+      href="http://mercurial.selenic.com/">Mercurial web site</a>.
       You can also download a free book, <a
-      href="http://hgbook.red-bean.com/">Distributed revision control
-      with Mercurial</a>.</p>
+      href="http://hgbook.red-bean.com/">Mercurial: The Definitive
+      Guide</a>.
+    </p>
 
-    <p>By default, Mercurial installs to <tt>C:\Program Files\Mercurial</tt>.  The
-      Mercurial command is called <tt>hg.exe</tt>.</p>
+    <p>
+      By default, Mercurial installs to <tt>C:\Program
+      Files\Mercurial</tt>. The Mercurial command is called
+      <tt>hg.exe</tt>.
+    </p>
 
     <h1>Testing Mercurial after you've installed it</h1>
 
-    <p>The easiest way to check that Mercurial is installed properly is to
-      just type the following at the command prompt:</p>
+    <p>
+      The easiest way to check that Mercurial is installed properly is
+      to just type the following at the command prompt:
+    </p>
 
     <pre>
 hg
 </pre>
 
-    <p>This command should print a useful help message.  If it does,
-      other Mercurial commands should work fine for you.</p>
+    <p>
+      This command should print a useful help message. If it does,
+      other Mercurial commands should work fine for you.
+    </p>
 
     <h1>Configuration notes</h1>
-	<h4>Default editor</h4>
-	The default editor for commit messages is 'notepad'. You can set the EDITOR
-    (or HGEDITOR) environment variable to specify your preference or set it in
-    mercurial.ini:
+    <h4>Default editor</h4>
+    <p>
+      The default editor for commit messages is 'notepad'. You can set
+      the <tt>EDITOR</tt> (or <tt>HGEDITOR</tt>) environment variable
+      to specify your preference or set it in <tt>mercurial.ini</tt>:
+    </p>
     <pre>
 [ui]
 editor = whatever
 </pre>
 
-	<h4>Configuring a Merge program</h4>
-	It should be emphasized that Mercurial by itself doesn't attempt to do a
-	Merge at the file level, neither does it make any attempt to Resolve the conflicts.
+    <h4>Configuring a Merge program</h4>
+    <p>
+      It should be emphasized that Mercurial by itself doesn't attempt
+      to do a Merge at the file level, neither does it make any
+      attempt to Resolve the conflicts.
+    </p>
 
-    By default, Mercurial will use the merge program defined by the HGMERGE environment
-    variable, or uses the one defined in the mercurial.ini file. (see <a href="http://www.selenic.com/mercurial/wiki/index.cgi/MergeProgram">MergeProgram</a> on the Mercurial Wiki for more information)
+    <p>
+      By default, Mercurial will use the merge program defined by the
+      <tt>HGMERGE</tt> environment variable, or uses the one defined
+      in the <tt>mercurial.ini</tt> file. (see <a
+      href="http://mercurial.selenic.com/wiki/MergeProgram">MergeProgram</a>
+      on the Mercurial Wiki for more information)
+    </p>
 
     <h1>Reporting problems</h1>
 
-    <p>Before you report any problems, please consult the <a
-	href="http://www.selenic.com/mercurial">Mercurial web site</a> and
-      see if your question is already in our list of <a
-	href="http://www.selenic.com/mercurial/wiki/index.cgi/FAQ">Frequently
-	Answered Questions</a> (the "FAQ").
+    <p>
+      Before you report any problems, please consult the <a
+      href="http://mercurial.selenic.com/">Mercurial web site</a>
+      and see if your question is already in our list of <a
+      href="http://mercurial.selenic.com/wiki/FAQ">Frequently
+      Answered Questions</a> (the "FAQ").
+    </p>
 
-    <p>If you cannot find an answer to your question, please feel
-      free to send mail to the Mercurial mailing list, at <a
-	href="mailto:mercurial@selenic.com">mercurial@selenic.com</a>.
+    <p>
+      If you cannot find an answer to your question, please feel free
+      to send mail to the Mercurial mailing list, at <a
+      href="mailto:mercurial@selenic.com">mercurial@selenic.com</a>.
       <b>Remember</b>, the more useful information you include in your
-      report, the easier it will be for us to help you!</p>
+      report, the easier it will be for us to help you!
+    </p>
 
-    <p>If you are IRC-savvy, that's usually the fastest way to get
-      help.  Go to <tt>#mercurial</tt> on
-      <tt>irc.freenode.net</tt>.</p>
+    <p>
+      If you are IRC-savvy, that's usually the fastest way to get
+      help. Go to <tt>#mercurial</tt> on <tt>irc.freenode.net</tt>.
+    </p>
 
     <h1>Author and copyright information</h1>
 
-    <p>Mercurial was written by <a href="http://www.selenic.com">Matt
-	Mackall</a>, and is maintained by Matt and a team of
-	volunteers.</p>
+    <p>
+      Mercurial was written by <a href="http://www.selenic.com">Matt
+      Mackall</a>, and is maintained by Matt and a team of volunteers.
+    </p>
 
-    <p>The Windows installer was written by <a
-	href="http://www.serpentine.com/blog">Bryan
-	O'Sullivan</a>.</p>
+    <p>
+      The Windows installer was written by <a
+      href="http://www.serpentine.com/blog">Bryan O'Sullivan</a>.
+    </p>
 
-    <p>Mercurial is Copyright 2005-2007 Matt Mackall and others.
-	See the <tt>Contributors.txt</tt> file for a list of contributors.</p>
+    <p>
+      Mercurial is Copyright 2005-2009 Matt Mackall and others. See
+      the <tt>Contributors.txt</tt> file for a list of contributors.
+    </p>
 
-    <p>Mercurial is free software; you can redistribute it and/or
+    <p>
+      Mercurial is free software; you can redistribute it and/or
       modify it under the terms of the <a
-	href="http://www.gnu.org/copyleft/gpl.html">GNU General Public
-	License</a> as published by the Free Software Foundation; either
-      version 2 of the License, or (at your option) any later
-      version.</p>
+      href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt">GNU
+      General Public License version 2</a> as published by the Free
+      Software Foundation.
+    </p>
 
-    <p>Mercurial is distributed in the hope that it will be useful,
-      but <b>without any warranty</b>; without even the implied
-      warranty of <b>merchantability</b> or <b>fitness for a
-      particular purpose</b>.  See the GNU General Public License for
-      more details.</p>
+    <p>
+      Mercurial is distributed in the hope that it will be useful, but
+      <b>without any warranty</b>; without even the implied warranty
+      of <b>merchantability</b> or <b>fitness for a particular
+      purpose</b>. See the GNU General Public License for more
+      details.
+    </p>
   </body>
 </html>
--- a/mercurial-tests/testData/bin/ReleaseNotes.txt	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/ReleaseNotes.txt	Wed Dec 09 11:14:30 2009 +0300
@@ -6,4 +6,4 @@
 
 Also check the release notes at:
 
- http://www.selenic.com/mercurial/wiki/index.cgi/WhatsNew
+ http://mercurial.selenic.com/wiki/WhatsNew
--- a/mercurial-tests/testData/bin/Templates/atom/changelog.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/atom/changelog.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,10 +1,10 @@
-#header#
+{header}
  <!-- Changelog -->
  <id>{urlbase}{url}</id>
  <link rel="self" href="{urlbase}{url}atom-log"/>
  <link rel="alternate" href="{urlbase}{url}"/>
- <title>#repo|escape# Changelog</title>
- #latestentry%feedupdated#
+ <title>{repo|escape} Changelog</title>
+ {latestentry%feedupdated}
 
-#entries%changelogentry#
+{entries%changelogentry}
 </feed>
--- a/mercurial-tests/testData/bin/Templates/atom/changelogentry.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/atom/changelogentry.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,16 +1,16 @@
  <entry>
-  <title>#desc|strip|firstline|strip|escape#</title>
-  <id>http://www.selenic.com/mercurial/#changeset-{node}</id>
-  <link href="{urlbase}{url}rev/{node}"/>
+  <title>{desc|strip|firstline|strip|escape|nonempty}</title>
+  <id>{urlbase}{url}#changeset-{node}</id>
+  <link href="{urlbase}{url}rev/{node|short}"/>
   <author>
-   <name>#author|person|escape#</name>
-   <email>#author|email|obfuscate#</email>
+   <name>{author|person|escape}</name>
+   <email>{author|email|obfuscate}</email>
   </author>
-  <updated>#date|rfc3339date#</updated>
-  <published>#date|rfc3339date#</published>
+  <updated>{date|rfc3339date}</updated>
+  <published>{date|rfc3339date}</published>
   <content type="xhtml">
    <div xmlns="http://www.w3.org/1999/xhtml">
-    <pre xml:space="preserve">#desc|escape#</pre>
+    <pre xml:space="preserve">{desc|escape|nonempty}</pre>
    </div>
   </content>
  </entry>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/atom/error.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,17 @@
+{header}
+ <!-- Error -->
+ <id>{urlbase}{url}</id>
+ <link rel="self" href="{urlbase}{url}atom-log"/>
+ <link rel="alternate" href="{urlbase}{url}"/>
+ <title>Error</title>
+ <updated>1970-01-01T00:00:00+00:00</updated>
+ <entry>
+  <title>Error</title>
+  <id>http://mercurial.selenic.com/#error</id>
+  <author>
+    <name>mercurial</name>
+  </author>
+  <updated>1970-01-01T00:00:00+00:00</updated>
+  <content type="text">{error|escape}</content>
+ </entry>
+</feed>
--- a/mercurial-tests/testData/bin/Templates/atom/filelog.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/atom/filelog.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,8 +1,8 @@
-#header#
+{header}
  <id>{urlbase}{url}atom-log/tip/{file|escape}</id>
- <link rel="self" href="{urlbase}{url}atom-log/tip/{file|escape}"/>
- <title>#repo|escape#: #file|escape# history</title>
- #latestentry%feedupdated#
+ <link rel="self" href="{urlbase}{url}atom-log/tip/{file|urlescape}"/>
+ <title>{repo|escape}: {file|escape} history</title>
+ {latestentry%feedupdated}
 
-#entries%changelogentry#
+{entries%changelogentry}
 </feed>
--- a/mercurial-tests/testData/bin/Templates/atom/map	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/atom/map	Wed Dec 09 11:14:30 2009 +0300
@@ -1,5 +1,5 @@
 default = 'changelog'
-feedupdated = '<updated>#date|rfc3339date#</updated>'
+feedupdated = '<updated>{date|rfc3339date}</updated>'
 mimetype = 'application/atom+xml; charset={encoding}'
 header = header.tmpl
 changelog = changelog.tmpl
@@ -8,3 +8,4 @@
 filelogentry = filelogentry.tmpl
 tags = tags.tmpl
 tagentry = tagentry.tmpl
+error = error.tmpl
--- a/mercurial-tests/testData/bin/Templates/atom/tagentry.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/atom/tagentry.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,8 +1,8 @@
  <entry>
-  <title>#tag|escape#</title>
-  <link rel="alternate" href="{urlbase}{url}rev/{node}"/>
-  <id>http://www.selenic.com/mercurial/#tag-{node}</id>
-  <updated>#date|rfc3339date#</updated>
-  <published>#date|rfc3339date#</published>
-  <content type="text">#tag|strip|escape#</content>
+  <title>{tag|escape}</title>
+  <link rel="alternate" href="{urlbase}{url}rev/{node|short}"/>
+  <id>{urlbase}{url}#tag-{node}</id>
+  <updated>{date|rfc3339date}</updated>
+  <published>{date|rfc3339date}</published>
+  <content type="text">{tag|strip|escape}</content>
  </entry>
--- a/mercurial-tests/testData/bin/Templates/atom/tags.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/atom/tags.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,11 +1,11 @@
-#header#
+{header}
  <id>{urlbase}{url}</id>
  <link rel="self" href="{urlbase}{url}atom-tags"/>
  <link rel="alternate" href="{urlbase}{url}tags"/>
- <title>#repo|escape#: tags</title>
- <summary>#repo|escape# tag history</summary>
+ <title>{repo|escape}: tags</title>
+ <summary>{repo|escape} tag history</summary>
  <author><name>Mercurial SCM</name></author>
- #latestentry%feedupdated#
+ {latestentry%feedupdated}
 
-#entriesnotip%tagentry#
+{entriesnotip%tagentry}
 </feed>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/gitweb/branches.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,30 @@
+{header}
+<title>{repo|escape}: Branches</title>
+<link rel="alternate" type="application/atom+xml"
+   href="{url}atom-tags" title="Atom feed for {repo|escape}"/>
+<link rel="alternate" type="application/rss+xml"
+   href="{url}rss-tags" title="RSS feed for {repo|escape}"/>
+</head>
+<body>
+
+<div class="page_header">
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / branches
+</div>
+
+<div class="page_nav">
+<a href="{url}summary{sessionvars%urlparameter}">summary</a> |
+<a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
+<a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
+<a href="{url}tags{sessionvars%urlparameter}">tags</a> |
+branches |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
+<br/>
+</div>
+
+<div class="title">&nbsp;</div>
+<table cellspacing="0">
+{entries%branchentry}
+</table>
+
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/changelog.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/changelog.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,14 +1,14 @@
-#header#
-<title>#repo|escape#: Changelog</title>
+{header}
+<title>{repo|escape}: Changelog</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / changelog
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / changelog
 </div>
 
 <form action="{url}log">
@@ -19,15 +19,21 @@
 </form>
 
 <div class="page_nav">
-<a href="{url}summary{sessionvars%urlparameter}">summary</a> | <a href="{url}shortlog/#rev#{sessionvars%urlparameter}">shortlog</a> | changelog | <a href="{url}tags{sessionvars%urlparameter}">tags</a> | <a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a>#archives%archiveentry#
+<a href="{url}summary{sessionvars%urlparameter}">summary</a> |
+<a href="{url}shortlog/{rev}{sessionvars%urlparameter}">shortlog</a> |
+changelog |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
+<a href="{url}tags{sessionvars%urlparameter}">tags</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>{archives%archiveentry}
 <br/>
-#changenav%naventry#<br/>
+{changenav%naventry}<br/>
 </div>
 
-#entries%changelogentry#
+{entries%changelogentry}
 
 <div class="page_nav">
-#changenav%naventry#<br/>
+{changenav%naventry}<br/>
 </div>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/changelogentry.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/changelogentry.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,14 +1,14 @@
 <div>
-<a class="title" href="{url}rev/#node|short#{sessionvars%urlparameter}"><span class="age">#date|age# ago</span>#desc|strip|firstline|escape#<span class="logtags"> {inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a>
+<a class="title" href="{url}rev/{node|short}{sessionvars%urlparameter}"><span class="age">{date|age}</span>{desc|strip|firstline|escape|nonempty}<span class="logtags"> {inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a>
 </div>
 <div class="title_text">
 <div class="log_link">
-<a href="{url}rev/#node|short#{sessionvars%urlparameter}">changeset</a><br/>
+<a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a><br/>
 </div>
-<i>#author|obfuscate# [#date|rfc822date#] rev #rev#</i><br/>
+<i>{author|obfuscate} [{date|rfc822date}] rev {rev}</i><br/>
 </div>
 <div class="log_body">
-#desc|strip|escape|addbreaks#
+{desc|strip|escape|addbreaks|nonempty}
 <br/>
 <br/>
 </div>
--- a/mercurial-tests/testData/bin/Templates/gitweb/changeset.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/changeset.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,42 +1,50 @@
-#header#
+{header}
 <title>{repo|escape}: changeset {rev}:{node|short}</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="#url#summary{sessionvars%urlparameter}">#repo|escape#</a> / changeset
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / changeset
 </div>
 
 <div class="page_nav">
-<a href="{url}summary{sessionvars%urlparameter}">summary</a> | <a href="{url}shortlog/#rev#{sessionvars%urlparameter}">shortlog</a> | <a href="{url}log/#rev#{sessionvars%urlparameter}">changelog</a> | <a href="{url}tags{sessionvars%urlparameter}">tags</a> | <a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a> | changeset | <a href="{url}raw-rev/#node|short#">raw</a> #archives%archiveentry#<br/>
+<a href="{url}summary{sessionvars%urlparameter}">summary</a> |
+<a href="{url}shortlog/{rev}{sessionvars%urlparameter}">shortlog</a> |
+<a href="{url}log/{rev}{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
+<a href="{url}tags{sessionvars%urlparameter}">tags</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a> |
+changeset |
+<a href="{url}raw-rev/{node|short}">raw</a> {archives%archiveentry}<br/>
 </div>
 
 <div>
-<a class="title" href="{url}raw-rev/#node|short#">#desc|strip|escape|firstline# <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a>
+<a class="title" href="{url}raw-rev/{node|short}">{desc|strip|escape|firstline|nonempty} <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a>
 </div>
 <div class="title_text">
 <table cellspacing="0">
-<tr><td>author</td><td>#author|obfuscate#</td></tr>
-<tr><td></td><td>#date|date# (#date|age# ago)</td></tr>
-#branch%changesetbranch#
+<tr><td>author</td><td>{author|obfuscate}</td></tr>
+<tr><td></td><td>{date|date} ({date|age})</td></tr>
+{branch%changesetbranch}
 <tr><td>changeset {rev}</td><td style="font-family:monospace">{node|short}</td></tr>
-#parent%changesetparent#
-#child%changesetchild#
+{parent%changesetparent}
+{child%changesetchild}
 </table></div>
 
 <div class="page_body">
-#desc|strip|escape|addbreaks#
+{desc|strip|escape|addbreaks|nonempty}
 </div>
 <div class="list_head"></div>
 <div class="title_text">
 <table cellspacing="0">
-#files#
+{files}
 </table></div>
 
-<div class="page_body">#diff#</div>
+<div class="page_body">{diff}</div>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/error.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/error.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,18 +1,18 @@
-#header#
-<title>#repo|escape#: Error</title>
+{header}
+<title>{repo|escape}: Error</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / error
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / error
 </div>
 
 <div class="page_nav">
-<a href="{url}summary{sessionvars%urlparameter}">summary</a> | <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> | <a href="{url}log{sessionvars%urlparameter}">changelog</a> | <a href="{url}tags{sessionvars%urlparameter}">tags</a> | <a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a><br/>
+<a href="{url}summary{sessionvars%urlparameter}">summary</a> | <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> | <a href="{url}log{sessionvars%urlparameter}">changelog</a> | <a href="{url}tags{sessionvars%urlparameter}">tags</a> | <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a><br/>
 </div>
 
 <div class="page_body">
@@ -22,4 +22,4 @@
 {error|escape}
 </div>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/fileannotate.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/fileannotate.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,59 +1,61 @@
-#header#
+{header}
 <title>{repo|escape}: {file|escape}@{node|short} (annotated)</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / annotate
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / annotate
 </div>
 
 <div class="page_nav">
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
-<a href="{url}file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a> |
-<a href="{url}rev/#node|short#{sessionvars%urlparameter}">changeset</a> |
-<a href="{url}file/{node|short}/#file|urlescape#{sessionvars%urlparameter}">file</a> |
-<a href="{url}log/{node|short}/#file|urlescape#{sessionvars%urlparameter}">revisions</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a> |
+<a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
+<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
+<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
 annotate |
 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
-<a href="{url}raw-annotate/{node|short}/#file|urlescape#">raw</a><br/>
+<a href="{url}raw-annotate/{node|short}/{file|urlescape}">raw</a><br/>
 </div>
 
-<div class="title">#file|escape#</div>
+<div class="title">{file|escape}</div>
 
 <div class="title_text">
 <table cellspacing="0">
 <tr>
  <td>author</td>
- <td>#author|obfuscate#</td></tr>
+ <td>{author|obfuscate}</td></tr>
 <tr>
  <td></td>
- <td>#date|date# (#date|age# ago)</td></tr>
-#branch%filerevbranch#
+ <td>{date|date} ({date|age})</td></tr>
+{branch%filerevbranch}
 <tr>
  <td>changeset {rev}</td>
- <td style="font-family:monospace"><a class="list" href="{url}rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>
-#parent%fileannotateparent#
-#child%fileannotatechild#
+ <td style="font-family:monospace"><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>
+{parent%fileannotateparent}
+{child%fileannotatechild}
 <tr>
  <td>permissions</td>
- <td style="font-family:monospace">#permissions|permissions#</td></tr>
+ <td style="font-family:monospace">{permissions|permissions}</td></tr>
 </table>
 </div>
 
 <div class="page_path">
-{desc|strip|escape|addbreaks}
+{desc|strip|escape|addbreaks|nonempty}
 </div>
 <div class="page_body">
 <table>
-#annotate%annotateline#
+{annotate%annotateline}
 </table>
 </div>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/filediff.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/filediff.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,21 +1,23 @@
 {header}
 <title>{repo|escape}: diff {file|escape}</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
    href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / diff
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / diff
 </div>
 
 <div class="page_nav">
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
 <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a> |
 <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
 <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
--- a/mercurial-tests/testData/bin/Templates/gitweb/filelog.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/filelog.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,38 +1,40 @@
-#header#
-<title>#repo|escape#: File revisions</title>
+{header}
+<title>{repo|escape}: File revisions</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / file revisions
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / file revisions
 </div>
 
 <div class="page_nav">
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
-<a href="{url}file/{node|short}/#file|urlescape#{sessionvars%urlparameter}">file</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
 revisions |
-<a href="{url}annotate/{node|short}/#file|urlescape#{sessionvars%urlparameter}">annotate</a> |
+<a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
-<a href="{url}rss-log/#node|short#/#file|urlescape#">rss</a>
+<a href="{url}rss-log/{node|short}/{file|urlescape}">rss</a>
 <br/>
 {nav%filenaventry}
 </div>
 
-<div class="title" >#file|urlescape#</div>
+<div class="title" >{file|urlescape}</div>
 
 <table>
-#entries%filelogentry#
+{entries%filelogentry}
 </table>
 
 <div class="page_nav">
 {nav%filenaventry}
 </div>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/filerevision.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/filerevision.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,58 +1,60 @@
-#header#
+{header}
 <title>{repo|escape}: {file|escape}@{node|short}</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / file revision
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / file revision
 </div>
 
 <div class="page_nav">
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
-<a href="{url}file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a> |
-<a href="{url}rev/#node|short#{sessionvars%urlparameter}">changeset</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a> |
+<a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
 file |
-<a href="{url}log/{node|short}/#file|urlescape#{sessionvars%urlparameter}">revisions</a> |
-<a href="{url}annotate/{node|short}/#file|urlescape#{sessionvars%urlparameter}">annotate</a> |
+<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
+<a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
 <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
-<a href="{url}raw-file/{node|short}/#file|urlescape#">raw</a><br/>
+<a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a><br/>
 </div>
 
-<div class="title">#file|escape#</div>
+<div class="title">{file|escape}</div>
 
 <div class="title_text">
 <table cellspacing="0">
 <tr>
  <td>author</td>
- <td>#author|obfuscate#</td></tr>
+ <td>{author|obfuscate}</td></tr>
 <tr>
  <td></td>
- <td>#date|date# (#date|age# ago)</td></tr>
-#branch%filerevbranch#
+ <td>{date|date} ({date|age})</td></tr>
+{branch%filerevbranch}
 <tr>
  <td>changeset {rev}</td>
- <td style="font-family:monospace"><a class="list" href="{url}rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>
-#parent%filerevparent#
-#child%filerevchild#
+ <td style="font-family:monospace"><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>
+{parent%filerevparent}
+{child%filerevchild}
 <tr>
  <td>permissions</td>
- <td style="font-family:monospace">#permissions|permissions#</td></tr>
+ <td style="font-family:monospace">{permissions|permissions}</td></tr>
 </table>
 </div>
 
 <div class="page_path">
-{desc|strip|escape|addbreaks}
+{desc|strip|escape|addbreaks|nonempty}
 </div>
 
 <div class="page_body">
-#text%fileline#
+{text%fileline}
 </div>
 
-#footer#
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/gitweb/graph.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,121 @@
+{header}
+<title>{repo|escape}: Graph</title>
+<link rel="alternate" type="application/atom+xml"
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
+<link rel="alternate" type="application/rss+xml"
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
+<!--[if IE]><script type="text/javascript" src="{staticurl}excanvas.js"></script><![endif]-->
+</head>
+<body>
+
+<div class="page_header">
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / graph
+</div>
+
+<form action="{url}log">
+{sessionvars%hiddenformentry}
+<div class="search">
+<input type="text" name="rev"  />
+</div>
+</form>
+<div class="page_nav">
+<a href="{url}summary{sessionvars%urlparameter}">summary</a> |
+<a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
+<a href="{url}log/{rev}{sessionvars%urlparameter}">changelog</a> |
+graph |
+<a href="{url}tags{sessionvars%urlparameter}">tags</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
+<br/>
+<a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
+<a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
+| {changenav%navgraphentry}<br/>
+</div>
+
+<div class="title">&nbsp;</div>
+
+<noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
+
+<div id="wrapper">
+<ul id="nodebgs"></ul>
+<canvas id="graph" width="224" height="{canvasheight}"></canvas>
+<ul id="graphnodes"></ul>
+</div>
+
+<script type="text/javascript" src="{staticurl}graph.js"></script>
+<script>
+<!-- hide script content
+
+var data = {jsdata|json};
+var graph = new Graph();
+graph.scale({bg_height});
+
+graph.edge = function(x0, y0, x1, y1, color) {
+	
+	this.setColor(color, 0.0, 0.65);
+	this.ctx.beginPath();
+	this.ctx.moveTo(x0, y0);
+	this.ctx.lineTo(x1, y1);
+	this.ctx.stroke();
+	
+}
+
+var revlink = '<li style="_STYLE"><span class="desc">';
+revlink += '<a class="list" href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID"><b>_DESC</b></a>';
+revlink += '</span> _TAGS';
+revlink += '<span class="info">_DATE ago, by _USER</span></li>';
+
+graph.vertex = function(x, y, color, parity, cur) {
+	
+	this.ctx.beginPath();
+	color = this.setColor(color, 0.25, 0.75);
+	this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
+	this.ctx.fill();
+	
+	var bg = '<li class="bg parity' + parity + '"></li>';
+	var left = (this.columns + 1) * this.bg_height;
+	var nstyle = 'padding-left: ' + left + 'px;';
+	var item = revlink.replace(/_STYLE/, nstyle);
+	item = item.replace(/_PARITY/, 'parity' + parity);
+	item = item.replace(/_NODEID/, cur[0]);
+	item = item.replace(/_NODEID/, cur[0]);
+	item = item.replace(/_DESC/, cur[3]);
+	item = item.replace(/_USER/, cur[4]);
+	item = item.replace(/_DATE/, cur[5]);
+	
+	var tagspan = '';
+	if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
+		tagspan = '<span class="logtags">';
+		if (cur[6][1]) {
+			tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
+			tagspan += cur[6][0] + '</span> ';
+		} else if (!cur[6][1] && cur[6][0] != 'default') {
+			tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
+			tagspan += cur[6][0] + '</span> ';
+		}
+		if (cur[7].length) {
+			for (var t in cur[7]) {
+				var tag = cur[7][t];
+				tagspan += '<span class="tagtag">' + tag + '</span> ';
+			}
+		}
+		tagspan += '</span>';
+	}
+	
+	item = item.replace(/_TAGS/, tagspan);
+	return [bg, item];
+	
+}
+
+graph.render(data);
+
+// stop hiding script -->
+</script>
+
+<div class="page_nav">
+<a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
+<a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
+| {changenav%navgraphentry}
+</div>
+
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/index.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/index.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,26 +1,26 @@
-#header#
+{header}
 <title>Mercurial repositories index</title>
 </head>
 <body>
 
 <div class="page_header">
-    <a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a>
+    <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a>
     Repositories list
 </div>
 
 <table cellspacing="0">
     <tr>
-        <td><a href="?sort=#sort_name#">Name</a></td>
-        <td><a href="?sort=#sort_description#">Description</a></td>
-        <td><a href="?sort=#sort_contact#">Contact</a></td>
-        <td><a href="?sort=#sort_lastchange#">Last change</a></td>
+        <td><a href="?sort={sort_name}">Name</a></td>
+        <td><a href="?sort={sort_description}">Description</a></td>
+        <td><a href="?sort={sort_contact}">Contact</a></td>
+        <td><a href="?sort={sort_lastchange}">Last change</a></td>
         <td>&nbsp;</td>
         <td>&nbsp;</td>
     </tr>
-    #entries%indexentry#
+    {entries%indexentry}
 </table>
 <div class="page_footer">
-#motd#
+{motd}
 </div>
 </body>
 </html>
--- a/mercurial-tests/testData/bin/Templates/gitweb/manifest.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/manifest.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,36 +1,38 @@
-#header#
-<title>#repo|escape#: files</title>
+{header}
+<title>{repo|escape}: files</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / files
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / files
 </div>
 
 <div class="page_nav">
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
 files |
-<a href="{url}rev/#node|short#{sessionvars%urlparameter}">changeset</a> #archives%archiveentry#<br/>
+<a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> {archives%archiveentry}<br/>
 </div>
 
-<div class="title">#path|escape# <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></div>
+<div class="title">{path|escape} <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></div>
 <table cellspacing="0">
-<tr class="parity#upparity#">
+<tr class="parity{upparity}">
 <td style="font-family:monospace">drwxr-xr-x</td>
 <td style="font-family:monospace"></td>
 <td style="font-family:monospace"></td>
-<td><a href="{url}file/#node|short##up|urlescape#{sessionvars%urlparameter}">[up]</a></td>
+<td><a href="{url}file/{node|short}{up|urlescape}{sessionvars%urlparameter}">[up]</a></td>
 <td class="link">&nbsp;</td>
 </tr>
-#dentries%direntry#
-#fentries%fileentry#
+{dentries%direntry}
+{fentries%fileentry}
 </table>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/map	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/map	Wed Dec 09 11:14:30 2009 +0300
@@ -9,55 +9,240 @@
 notfound = notfound.tmpl
 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
+navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
-filedifflink = '<a href="#url#diff/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#file|escape#</a> '
-filenodelink = '<tr class="parity#parity#"><td><a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">#file|escape#</a></td><td></td><td class="link"><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a> | <a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a> | <a href="#url#diff/#node|short#/#file|urlescape#{sessionvars%urlparameter}">diff</a> | <a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a></td></tr>'
+filedifflink = '<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
+filenodelink = '
+  <tr class="parity{parity}">
+    <td><a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a></td>
+    <td></td>
+    <td class="link">
+      <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
+      <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> |
+      <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
+      <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
+    </td>
+  </tr>'
+filenolink = '
+  <tr class="parity{parity}">
+    <td><a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a></td>
+    <td></td>
+    <td class="link">
+      file |
+      annotate |
+      <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> |
+      <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a>
+    </td>
+  </tr>'
 fileellipses = '...'
 changelogentry = changelogentry.tmpl
 searchentry = changelogentry.tmpl
 changeset = changeset.tmpl
 manifest = manifest.tmpl
-direntry = '<tr class="parity#parity#"><td style="font-family:monospace">drwxr-xr-x</td><td style="font-family:monospace"></td><td style="font-family:monospace"></td><td><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">#basename|escape#</a></td><td class="link"><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a></td></tr>'
-fileentry = '<tr class="parity#parity#"><td style="font-family:monospace">#permissions|permissions#</td><td style="font-family:monospace" align=right>#date|isodate#</td><td style="font-family:monospace" align=right>#size#</td><td class="list"><a class="list" href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#basename|escape#</a></td><td class="link"><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a> | <a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a> | <a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a></td></tr>'
+direntry = '
+  <tr class="parity{parity}">
+    <td style="font-family:monospace">drwxr-xr-x</td>
+    <td style="font-family:monospace"></td>
+    <td style="font-family:monospace"></td>
+    <td>
+      <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">{basename|escape}</a>
+      <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">{emptydirs|escape}</a>
+    </td>
+    <td class="link">
+      <a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">files</a>
+    </td>
+  </tr>'
+fileentry = '
+  <tr class="parity{parity}">
+    <td style="font-family:monospace">{permissions|permissions}</td>
+    <td style="font-family:monospace" align=right>{date|isodate}</td>
+    <td style="font-family:monospace" align=right>{size}</td>
+    <td class="list">
+      <a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{basename|escape}</a>
+    </td>
+    <td class="link">
+      <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> |
+      <a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">revisions</a> |
+      <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a>
+    </td>
+  </tr>'
 filerevision = filerevision.tmpl
 fileannotate = fileannotate.tmpl
 filediff = filediff.tmpl
 filelog = filelog.tmpl
-fileline = '<div style="font-family:monospace" class="parity#parity#"><pre><a class="linenr" href="##lineid#" id="#lineid#">#linenumber#</a> #line|escape#</pre></div>'
-annotateline = '<tr style="font-family:monospace" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}#l{targetline}">#author|obfuscate#@#rev#</a></td><td><pre><a class="linenr" href="##lineid#" id="#lineid#">#linenumber#</a></pre></td><td><pre>#line|escape#</pre></td></tr>'
-difflineplus = '<span style="color:#008800;"><a class="linenr" href="##lineid#" id="#lineid#">#linenumber#</a> #line|escape#</span>'
-difflineminus = '<span style="color:#cc0000;"><a class="linenr" href="##lineid#" id="#lineid#">#linenumber#</a> #line|escape#</span>'
-difflineat = '<span style="color:#990099;"><a class="linenr" href="##lineid#" id="#lineid#">#linenumber#</a> #line|escape#</span>'
-diffline = '<span><a class="linenr" href="##lineid#" id="#lineid#">#linenumber#</a> #line|escape#</span>'
-changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+fileline = '
+  <div style="font-family:monospace" class="parity{parity}">
+    <pre><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</pre>
+  </div>'
+annotateline = '
+  <tr style="font-family:monospace" class="parity{parity}">
+    <td class="linenr" style="text-align: right;">
+      <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l{targetline}"
+         title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a>
+    </td>
+    <td><pre><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a></pre></td>
+    <td><pre>{line|escape}</pre></td>
+  </tr>'
+difflineplus = '<span style="color:#008800;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
+difflineminus = '<span style="color:#cc0000;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
+difflineat = '<span style="color:#990099;"><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
+diffline = '<span><a class="linenr" href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</span>'
+changelogparent = '
+  <tr>
+    <th class="parent">parent {rev}:</th>
+    <td class="parent">
+      <a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
+    </td>
+  </tr>'
 changesetbranch = '<tr><td>branch</td><td>{name}</td></tr>'
-changesetparent = '<tr><td>parent {rev}</td><td style="font-family:monospace"><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
+changesetparent = '
+  <tr>
+    <td>parent {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
+    </td>
+  </tr>'
 filerevbranch = '<tr><td>branch</td><td>{name}</td></tr>'
-filerevparent = '<tr><td>parent {rev}</td><td style="font-family:monospace"><a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a></td></tr>'
+filerevparent = '
+  <tr>
+    <td>parent {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
+        {rename%filerename}{node|short}
+      </a>
+    </td>
+  </tr>'
 filerename = '{file|escape}@'
-filelogrename = '| <a href="{url}file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">base</a>'
-fileannotateparent = '<tr><td>parent {rev}</td><td style="font-family:monospace"><a class="list" href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a></td></tr>'
-changelogchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="{url}rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-changesetchild = '<tr><td>child {rev}</td><td style="font-family:monospace"><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
-filerevchild = '<tr><td>child {rev}</td><td style="font-family:monospace"><a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
-fileannotatechild = '<tr><td>child {rev}</td><td style="font-family:monospace"><a class="list" href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
+filelogrename = '| <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">base</a>'
+fileannotateparent = '
+  <tr>
+    <td>parent {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
+        {rename%filerename}{node|short}
+      </a>
+    </td>
+  </tr>'
+changelogchild = '
+  <tr>
+    <th class="child">child {rev}:</th>
+    <td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
+  </tr>'
+changesetchild = '
+  <tr>
+    <td>child {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>
+    </td>
+  </tr>'
+filerevchild = '
+  <tr>
+    <td>child {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
+    </tr>'
+fileannotatechild = '
+  <tr>
+    <td>child {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
+    </tr>'
 tags = tags.tmpl
-tagentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}"><b>#tag|escape#</b></a></td><td class="link"><a href="{url}rev/#node|short#{sessionvars%urlparameter}">changeset</a> | <a href="{url}log/#node|short#{sessionvars%urlparameter}">changelog</a> | <a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a></td></tr>'
-branchentry = '<tr class="parity{parity}"><td class="age"><i>{date|age} ago</i></td><td><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}"><b>{node|short}</b></a></td><td>{branch|escape}</td><td class="link"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> | <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> | <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a></td></tr>'
-diffblock = '<pre>#lines#</pre>'
-filediffparent = '<tr><td>parent {rev}</td><td style="font-family:monospace"><a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
-filelogparent = '<tr><td align="right">parent #rev#:&nbsp;</td><td><a href="{url}file/{node|short}/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-filediffchild = '<tr><td>child {rev}</td><td style="font-family:monospace"><a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
-filelogchild = '<tr><td align="right">child #rev#:&nbsp;</td><td><a href="{url}file{node|short}/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+tagentry = '
+  <tr class="parity{parity}">
+    <td class="age"><i>{date|age}</i></td>
+    <td><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}"><b>{tag|escape}</b></a></td>
+    <td class="link">
+      <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
+      <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
+      <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
+    </td>
+  </tr>'
+branches = branches.tmpl
+branchentry = '
+  <tr class="parity{parity}">
+    <td class="age"><i>{date|age}</i></td>
+    <td><a class="list" href="{url}shortlog/{node|short}{sessionvars%urlparameter}"><b>{node|short}</b></a></td>
+    <td class="{status}">{branch|escape}</td>
+    <td class="link">
+      <a href="{url}changeset/{node|short}{sessionvars%urlparameter}">changeset</a> |
+      <a href="{url}log/{node|short}{sessionvars%urlparameter}">changelog</a> |
+      <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
+    </td>
+  </tr>'
+diffblock = '<pre>{lines}</pre>'
+filediffparent = '
+  <tr>
+    <td>parent {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">
+        {node|short}
+      </a>
+    </td>
+  </tr>'
+filelogparent = '
+  <tr>
+    <td align="right">parent {rev}:&nbsp;</td>
+    <td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
+  </tr>'
+filediffchild = '
+  <tr>
+    <td>child {rev}</td>
+    <td style="font-family:monospace">
+      <a class="list" href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a>
+    </td>
+  </tr>'
+filelogchild = '
+  <tr>
+    <td align="right">child {rev}:&nbsp;</td>
+    <td><a href="{url}file{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td>
+  </tr>'
 shortlog = shortlog.tmpl
+graph = graph.tmpl
 tagtag = '<span class="tagtag" title="{name}">{name}</span> '
 branchtag = '<span class="branchtag" title="{name}">{name}</span> '
 inbranchtag = '<span class="inbranchtag" title="{name}">{name}</span> '
-shortlogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><i>#author|person#</i></td><td><a class="list" href="{url}rev/#node|short#{sessionvars%urlparameter}"><b>#desc|strip|firstline|escape#</b> <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a></td><td class="link" nowrap><a href="{url}rev/#node|short#{sessionvars%urlparameter}">changeset</a> | <a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a></td></tr>'
-filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="{url}rev/#node|short#{sessionvars%urlparameter}"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="{url}file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a>&nbsp;|&nbsp;<a href="{url}diff/#node|short#/#file|urlescape#{sessionvars%urlparameter}">diff</a>&nbsp;|&nbsp;<a href="{url}annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a> #rename%filelogrename#</td></tr>'
-archiveentry = ' | <a href="{url}archive/{node|short}{extension}">#type|escape#</a> '
-indexentry = '<tr class="parity{parity}"><td><a class="list" href="{url}{sessionvars%urlparameter}"><b>{name|escape}</b></a></td><td>{description}</td><td>{contact|obfuscate}</td><td class="age">{lastchange|age} ago</td><td class="indexlinks">{archives%indexarchiveentry}</td><td><div class="rss_logo"><a href="{url}rss-log">RSS</a> <a href="{url}atom-log">Atom</a></div></td></tr>\n'
+shortlogentry = '
+  <tr class="parity{parity}">
+    <td class="age"><i>{date|age}</i></td>
+    <td><i>{author|person}</i></td>
+    <td>
+      <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">
+        <b>{desc|strip|firstline|escape|nonempty}</b>
+        <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span>
+      </a>
+    </td>
+    <td class="link" nowrap>
+      <a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
+      <a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
+    </td>
+  </tr>'
+filelogentry = '
+  <tr class="parity{parity}">
+    <td class="age"><i>{date|age}</i></td>
+    <td>
+      <a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">
+        <b>{desc|strip|firstline|escape|nonempty}</b>
+      </a>
+    </td>
+    <td class="link">
+      <a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a>&nbsp;|&nbsp;<a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a>&nbsp;|&nbsp;<a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> {rename%filelogrename}</td>
+    </tr>'
+archiveentry = ' | <a href="{url}archive/{node|short}{extension}">{type|escape}</a> '
+indexentry = '
+  <tr class="parity{parity}">
+    <td>
+      <a class="list" href="{url}{sessionvars%urlparameter}">
+        <b>{name|escape}</b>
+      </a>
+    </td>
+    <td>{description}</td>
+    <td>{contact|obfuscate}</td>
+    <td class="age">{lastchange|age}</td>
+    <td class="indexlinks">{archives%indexarchiveentry}</td>
+    <td><div class="rss_logo"><a href="{url}rss-log">RSS</a> <a href="{url}atom-log">Atom</a></div></td>
+  </tr>\n'
 indexarchiveentry = ' <a href="{url}archive/{node|short}{extension}">{type|escape}</a> '
 index = index.tmpl
-urlparameter = '#separator##name#=#value|urlescape#'
-hiddenformentry = '<input type="hidden" name="#name#" value="#value|escape#" />'
+urlparameter = '{separator}{name}={value|urlescape}'
+hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
--- a/mercurial-tests/testData/bin/Templates/gitweb/notfound.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/notfound.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -5,7 +5,7 @@
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a> Not found: {repo|escape}
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a> Not found: {repo|escape}
 </div>
 
 <div class="page_body">
--- a/mercurial-tests/testData/bin/Templates/gitweb/search.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/search.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,19 +1,19 @@
-#header#
-<title>#repo|escape#: Search</title>
+{header}
+<title>{repo|escape}: Search</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / search
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / search
 
 <form action="{url}log">
 {sessionvars%hiddenformentry}
 <div class="search">
-<input type="text" name="rev" value="#query|escape#" />
+<input type="text" name="rev" value="{query|escape}" />
 </div>
 </form>
 </div>
@@ -22,13 +22,15 @@
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
-<a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a>#archives%archiveentry#
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>{archives%archiveentry}
 <br/>
 </div>
 
-<div class="title">searching for #query|escape#</div>
+<div class="title">searching for {query|escape}</div>
 
-#entries#
+{entries}
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/shortlog.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/shortlog.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,14 +1,14 @@
-#header#
-<title>#repo|escape#: Shortlog</title>
+{header}
+<title>{repo|escape}: Shortlog</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / shortlog
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / shortlog
 </div>
 
 <form action="{url}log">
@@ -20,20 +20,22 @@
 <div class="page_nav">
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 shortlog |
-<a href="{url}log/#rev#{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}log/{rev}{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
-<a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a>#archives%archiveentry#
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>{archives%archiveentry}
 <br/>
-#changenav%navshortentry#<br/>
+{changenav%navshortentry}<br/>
 </div>
 
 <div class="title">&nbsp;</div>
 <table cellspacing="0">
-#entries%shortlogentry#
+{entries%shortlogentry}
 </table>
 
 <div class="page_nav">
-#changenav%navshortentry#
+{changenav%navshortentry}
 </div>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/summary.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/summary.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,14 +1,14 @@
-#header#
-<title>#repo|escape#: Summary</title>
+{header}
+<title>{repo|escape}: Summary</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-log" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-log" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / summary
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / summary
 
 <form action="{url}log">
 {sessionvars%hiddenformentry}
@@ -22,27 +22,29 @@
 summary |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
-<a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a>#archives%archiveentry#
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>{archives%archiveentry}
 <br/>
 </div>
 
 <div class="title">&nbsp;</div>
 <table cellspacing="0">
-<tr><td>description</td><td>#desc#</td></tr>
-<tr><td>owner</td><td>#owner|obfuscate#</td></tr>
-<tr><td>last change</td><td>#lastchange|rfc822date#</td></tr>
+<tr><td>description</td><td>{desc}</td></tr>
+<tr><td>owner</td><td>{owner|obfuscate}</td></tr>
+<tr><td>last change</td><td>{lastchange|rfc822date}</td></tr>
 </table>
 
 <div><a  class="title" href="{url}shortlog{sessionvars%urlparameter}">changes</a></div>
 <table cellspacing="0">
-#shortlog#
+{shortlog}
 <tr class="light"><td colspan="4"><a class="list" href="{url}shortlog{sessionvars%urlparameter}">...</a></td></tr>
 </table>
 
 <div><a class="title" href="{url}tags{sessionvars%urlparameter}">tags</a></div>
 <table cellspacing="0">
-#tags#
+{tags}
 <tr class="light"><td colspan="3"><a class="list" href="{url}tags{sessionvars%urlparameter}">...</a></td></tr>
 </table>
 
@@ -53,4 +55,4 @@
   <td colspan="4"><a class="list"  href="#">...</a></td>
 </tr>
 </table>
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/gitweb/tags.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/gitweb/tags.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,28 +1,30 @@
-#header#
-<title>#repo|escape#: Tags</title>
+{header}
+<title>{repo|escape}: Tags</title>
 <link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for #repo|escape#"/>
+   href="{url}atom-tags" title="Atom feed for {repo|escape}"/>
 <link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+   href="{url}rss-tags" title="RSS feed for {repo|escape}"/>
 </head>
 <body>
 
 <div class="page_header">
-<a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">#repo|escape#</a> / tags
+<a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="{url}summary{sessionvars%urlparameter}">{repo|escape}</a> / tags
 </div>
 
 <div class="page_nav">
 <a href="{url}summary{sessionvars%urlparameter}">summary</a> |
 <a href="{url}shortlog{sessionvars%urlparameter}">shortlog</a> |
 <a href="{url}log{sessionvars%urlparameter}">changelog</a> |
+<a href="{url}graph{sessionvars%urlparameter}">graph</a> |
 tags |
-<a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a>
+<a href="{url}branches{sessionvars%urlparameter}">branches</a> |
+<a href="{url}file/{node|short}{sessionvars%urlparameter}">files</a>
 <br/>
 </div>
 
 <div class="title">&nbsp;</div>
 <table cellspacing="0">
-#entries%tagentry#
+{entries%tagentry}
 </table>
 
-#footer#
+{footer}
--- a/mercurial-tests/testData/bin/Templates/map-cmdline.compact	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/map-cmdline.compact	Wed Dec 09 11:14:30 2009 +0300
@@ -1,5 +1,6 @@
 changeset = '{rev}{tags}{parents}   {node|short}   {date|isodate}   {author|user}\n  {desc|firstline|strip}\n\n'
 changeset_quiet = '{rev}:{node|short}\n'
+changeset_verbose = '{rev}{tags}{parents}   {node|short}   {date|isodate}   {author}\n  {desc|strip}\n\n'
 start_tags = '['
 tag = '{tag},'
 last_tag = '{tag}]'
--- a/mercurial-tests/testData/bin/Templates/raw/changeset.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/raw/changeset.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,9 +1,9 @@
-#header#
+{header}
 # HG changeset patch
-# User #author#
-# Date #date|hgdate#
-# Node ID #node#
-#parent%changesetparent#
-#desc#
+# User {author}
+# Date {date|hgdate}
+# Node ID {node}
+{parent%changesetparent}
+{desc}
 
-#diff#
+{diff}
--- a/mercurial-tests/testData/bin/Templates/raw/error.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/raw/error.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,2 +1,2 @@
-#header#
-error: #error#
+{header}
+error: {error}
--- a/mercurial-tests/testData/bin/Templates/raw/fileannotate.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/raw/fileannotate.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,5 +1,5 @@
-#header#
-#annotate%annotateline#
-#footer#
+{header}
+{annotate%annotateline}
+{footer}
 
 
--- a/mercurial-tests/testData/bin/Templates/raw/filediff.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/raw/filediff.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,5 +1,5 @@
-#header#
-#diff#
-#footer#
+{header}
+{diff}
+{footer}
 
 
--- a/mercurial-tests/testData/bin/Templates/raw/index.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/raw/index.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,2 +1,2 @@
-#header#
-#entries%indexentry#
+{header}
+{entries%indexentry}
--- a/mercurial-tests/testData/bin/Templates/raw/map	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/raw/map	Wed Dec 09 11:14:30 2009 +0300
@@ -2,22 +2,22 @@
 header = ''
 footer = ''
 changeset = changeset.tmpl
-difflineplus = '#line#'
-difflineminus = '#line#'
-difflineat = '#line#'
-diffline = '#line#'
-changesetparent = '# Parent #node#'
-changesetchild = '# Child #node#'
+difflineplus = '{line}'
+difflineminus = '{line}'
+difflineat = '{line}'
+diffline = '{line}'
+changesetparent = '# Parent  {node}'
+changesetchild = '# Child   {node}'
 filenodelink = ''
-fileline = '#line#'
-diffblock = '#lines#'
+fileline = '{line}'
+diffblock = '{lines}'
 filediff = filediff.tmpl
 fileannotate = fileannotate.tmpl
-annotateline = '#author#@#rev#: #line#'
+annotateline = '{author|user}@{rev}: {line}'
 manifest = manifest.tmpl
 direntry = 'drwxr-xr-x {basename}\n'
 fileentry = '{permissions|permissions} {size} {basename}\n'
 index = index.tmpl
 notfound = notfound.tmpl
 error = error.tmpl
-indexentry = '#url#\n'
+indexentry = '{url}\n'
--- a/mercurial-tests/testData/bin/Templates/raw/notfound.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/raw/notfound.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,2 +1,2 @@
-#header#
-error: repository #repo# not found
+{header}
+error: repository {repo} not found
--- a/mercurial-tests/testData/bin/Templates/rss/changelog.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/rss/changelog.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,6 +1,6 @@
-#header#
-    <title>#repo|escape# Changelog</title>
-    <description>#repo|escape# Changelog</description>
-    #entries%changelogentry#
+{header}
+    <title>{repo|escape} Changelog</title>
+    <description>{repo|escape} Changelog</description>
+    {entries%changelogentry}
   </channel>
 </rss>
\ No newline at end of file
--- a/mercurial-tests/testData/bin/Templates/rss/changelogentry.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/rss/changelogentry.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,7 +1,7 @@
 <item>
-    <title>#desc|strip|firstline|strip|escape#</title>
-    <link>{urlbase}{url}rev/{node|short}</link>
-    <description><![CDATA[#desc|strip|escape|addbreaks#]]></description>
-    <author>#author|obfuscate#</author>
-    <pubDate>#date|rfc822date#</pubDate>
+    <title>{desc|strip|firstline|strip|escape}</title>
+    <guid isPermaLink="true">{urlbase}{url}rev/{node|short}</guid>
+    <description><![CDATA[{desc|strip|escape|addbreaks|nonempty}]]></description>
+    <author>{author|obfuscate}</author>
+    <pubDate>{date|rfc822date}</pubDate>
 </item>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/rss/error.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,10 @@
+{header}
+    <title>Error</title>
+    <description>Error</description>
+    <item>
+      <title>Error</title>
+      <description>{error|escape}</description>
+      <guid>http://mercurial.selenic.com/#error</guid>
+    </item>
+  </channel>
+</rss>
--- a/mercurial-tests/testData/bin/Templates/rss/filelog.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/rss/filelog.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,6 +1,6 @@
-#header#
-    <title>#repo|escape#: #file|escape# history</title>
-    <description>#file|escape# revision history</description>
-    #entries%filelogentry#
+{header}
+    <title>{repo|escape}: {file|escape} history</title>
+    <description>{file|escape} revision history</description>
+    {entries%filelogentry}
   </channel>
 </rss>
--- a/mercurial-tests/testData/bin/Templates/rss/filelogentry.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/rss/filelogentry.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,7 +1,7 @@
 <item>
-    <title>#desc|strip|firstline|strip|escape#</title>
-    <link>{urlbase}{url}log{#node|short#}/{file|urlescape}</link>
-    <description><![CDATA[#desc|strip|escape|addbreaks#]]></description>
-    <author>#author|obfuscate#</author>
-    <pubDate>#date|rfc822date#</pubDate>
+    <title>{desc|strip|firstline|strip|escape}</title>
+    <link>{urlbase}{url}log{{node|short}}/{file|urlescape}</link>
+    <description><![CDATA[{desc|strip|escape|addbreaks|nonempty}]]></description>
+    <author>{author|obfuscate}</author>
+    <pubDate>{date|rfc822date}</pubDate>
 </item>
--- a/mercurial-tests/testData/bin/Templates/rss/map	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/rss/map	Wed Dec 09 11:14:30 2009 +0300
@@ -7,3 +7,4 @@
 filelogentry = filelogentry.tmpl
 tags = tags.tmpl
 tagentry = tagentry.tmpl
+error = error.tmpl
--- a/mercurial-tests/testData/bin/Templates/rss/tagentry.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/rss/tagentry.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,6 +1,6 @@
 <item>
-    <title>#tag|escape#</title>
+    <title>{tag|escape}</title>
     <link>{urlbase}{url}rev/{node|short}</link>
-    <description><![CDATA[#tag|strip|escape|addbreaks#]]></description>
-    <pubDate>#date|rfc822date#</pubDate>
+    <description><![CDATA[{tag|strip|escape|addbreaks}]]></description>
+    <pubDate>{date|rfc822date}</pubDate>
 </item>
--- a/mercurial-tests/testData/bin/Templates/rss/tags.tmpl	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/rss/tags.tmpl	Wed Dec 09 11:14:30 2009 +0300
@@ -1,6 +1,6 @@
-#header#
-    <title>#repo|escape#: tags </title>
-    <description>#repo|escape# tag history</description>
-    #entriesnotip%tagentry#
+{header}
+    <title>{repo|escape}: tags </title>
+    <description>{repo|escape} tag history</description>
+    {entriesnotip%tagentry}
   </channel>
 </rss>
Binary file mercurial-tests/testData/bin/Templates/static/background.png has changed
Binary file mercurial-tests/testData/bin/Templates/static/coal-file.png has changed
Binary file mercurial-tests/testData/bin/Templates/static/coal-folder.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/static/excanvas.js	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,19 @@
+if(!window.CanvasRenderingContext2D){(function(){var I=Math,i=I.round,L=I.sin,M=I.cos,m=10,A=m/2,Q={init:function(a){var b=a||document;if(/MSIE/.test(navigator.userAgent)&&!window.opera){var c=this;b.attachEvent("onreadystatechange",function(){c.r(b)})}},r:function(a){if(a.readyState=="complete"){if(!a.namespaces["s"]){a.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml")}var b=a.createStyleSheet();b.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}";
+var c=a.getElementsByTagName("canvas");for(var d=0;d<c.length;d++){if(!c[d].getContext){this.initElement(c[d])}}}},q:function(a){var b=a.outerHTML,c=a.ownerDocument.createElement(b);if(b.slice(-2)!="/>"){var d="/"+a.tagName,e;while((e=a.nextSibling)&&e.tagName!=d){e.removeNode()}if(e){e.removeNode()}}a.parentNode.replaceChild(c,a);return c},initElement:function(a){a=this.q(a);a.getContext=function(){if(this.l){return this.l}return this.l=new K(this)};a.attachEvent("onpropertychange",V);a.attachEvent("onresize",
+W);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+"px"}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+"px"}else{a.height=a.clientHeight}return a}};function V(a){var b=a.srcElement;switch(a.propertyName){case "width":b.style.width=b.attributes.width.nodeValue+"px";b.getContext().clearRect();break;case "height":b.style.height=b.attributes.height.nodeValue+"px";b.getContext().clearRect();break}}function W(a){var b=a.srcElement;
+if(b.firstChild){b.firstChild.style.width=b.clientWidth+"px";b.firstChild.style.height=b.clientHeight+"px"}}Q.init();var R=[];for(var E=0;E<16;E++){for(var F=0;F<16;F++){R[E*16+F]=E.toString(16)+F.toString(16)}}function J(){return[[1,0,0],[0,1,0],[0,0,1]]}function G(a,b){var c=J();for(var d=0;d<3;d++){for(var e=0;e<3;e++){var g=0;for(var h=0;h<3;h++){g+=a[d][h]*b[h][e]}c[d][e]=g}}return c}function N(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=
+a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.d=a.d;b.e=a.e}function O(a){var b,c=1;a=String(a);if(a.substring(0,3)=="rgb"){var d=a.indexOf("(",3),e=a.indexOf(")",d+1),g=a.substring(d+1,e).split(",");b="#";for(var h=0;h<3;h++){b+=R[Number(g[h])]}if(g.length==4&&a.substr(3,1)=="a"){c=g[3]}}else{b=a}return[b,c]}function S(a){switch(a){case "butt":return"flat";case "round":return"round";
+case "square":default:return"square"}}function K(a){this.a=J();this.m=[];this.k=[];this.c=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=m*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement("div");b.style.width=a.clientWidth+"px";b.style.height=a.clientHeight+"px";b.style.overflow="hidden";b.style.position="absolute";a.appendChild(b);this.j=b;this.d=1;this.e=1}var j=K.prototype;j.clearRect=function(){this.j.innerHTML=
+"";this.c=[]};j.beginPath=function(){this.c=[]};j.moveTo=function(a,b){this.c.push({type:"moveTo",x:a,y:b});this.f=a;this.g=b};j.lineTo=function(a,b){this.c.push({type:"lineTo",x:a,y:b});this.f=a;this.g=b};j.bezierCurveTo=function(a,b,c,d,e,g){this.c.push({type:"bezierCurveTo",cp1x:a,cp1y:b,cp2x:c,cp2y:d,x:e,y:g});this.f=e;this.g=g};j.quadraticCurveTo=function(a,b,c,d){var e=this.f+0.6666666666666666*(a-this.f),g=this.g+0.6666666666666666*(b-this.g),h=e+(c-this.f)/3,l=g+(d-this.g)/3;this.bezierCurveTo(e,
+g,h,l,c,d)};j.arc=function(a,b,c,d,e,g){c*=m;var h=g?"at":"wa",l=a+M(d)*c-A,n=b+L(d)*c-A,o=a+M(e)*c-A,f=b+L(e)*c-A;if(l==o&&!g){l+=0.125}this.c.push({type:h,x:a,y:b,radius:c,xStart:l,yStart:n,xEnd:o,yEnd:f})};j.rect=function(a,b,c,d){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath()};j.strokeRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.stroke()};j.fillRect=function(a,
+b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill()};j.createLinearGradient=function(a,b,c,d){var e=new H("gradient");return e};j.createRadialGradient=function(a,b,c,d,e,g){var h=new H("gradientradial");h.n=c;h.o=g;h.i.x=a;h.i.y=b;return h};j.drawImage=function(a,b){var c,d,e,g,h,l,n,o,f=a.runtimeStyle.width,k=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var q=a.width,r=a.height;a.runtimeStyle.width=
+f;a.runtimeStyle.height=k;if(arguments.length==3){c=arguments[1];d=arguments[2];h=(l=0);n=(e=q);o=(g=r)}else if(arguments.length==5){c=arguments[1];d=arguments[2];e=arguments[3];g=arguments[4];h=(l=0);n=q;o=r}else if(arguments.length==9){h=arguments[1];l=arguments[2];n=arguments[3];o=arguments[4];c=arguments[5];d=arguments[6];e=arguments[7];g=arguments[8]}else{throw"Invalid number of arguments";}var s=this.b(c,d),t=[],v=10,w=10;t.push(" <g_vml_:group",' coordsize="',m*v,",",m*w,'"',' coordorigin="0,0"',
+' style="width:',v,";height:",w,";position:absolute;");if(this.a[0][0]!=1||this.a[0][1]){var x=[];x.push("M11='",this.a[0][0],"',","M12='",this.a[1][0],"',","M21='",this.a[0][1],"',","M22='",this.a[1][1],"',","Dx='",i(s.x/m),"',","Dy='",i(s.y/m),"'");var p=s,y=this.b(c+e,d),z=this.b(c,d+g),B=this.b(c+e,d+g);p.x=Math.max(p.x,y.x,z.x,B.x);p.y=Math.max(p.y,y.y,z.y,B.y);t.push("padding:0 ",i(p.x/m),"px ",i(p.y/m),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",x.join(""),", sizingmethod='clip');")}else{t.push("top:",
+i(s.y/m),"px;left:",i(s.x/m),"px;")}t.push(' ">','<g_vml_:image src="',a.src,'"',' style="width:',m*e,";"," height:",m*g,';"',' cropleft="',h/q,'"',' croptop="',l/r,'"',' cropright="',(q-h-n)/q,'"',' cropbottom="',(r-l-o)/r,'"'," />","</g_vml_:group>");this.j.insertAdjacentHTML("BeforeEnd",t.join(""))};j.stroke=function(a){var b=[],c=O(a?this.fillStyle:this.strokeStyle),d=c[0],e=c[1]*this.globalAlpha,g=10,h=10;b.push("<g_vml_:shape",' fillcolor="',d,'"',' filled="',Boolean(a),'"',' style="position:absolute;width:',
+g,";height:",h,';"',' coordorigin="0 0" coordsize="',m*g," ",m*h,'"',' stroked="',!a,'"',' strokeweight="',this.lineWidth,'"',' strokecolor="',d,'"',' path="');var l={x:null,y:null},n={x:null,y:null};for(var o=0;o<this.c.length;o++){var f=this.c[o];if(f.type=="moveTo"){b.push(" m ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="lineTo"){b.push(" l ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="close"){b.push(" x ")}else if(f.type=="bezierCurveTo"){b.push(" c ");
+var k=this.b(f.x,f.y),q=this.b(f.cp1x,f.cp1y),r=this.b(f.cp2x,f.cp2y);b.push(i(q.x),",",i(q.y),",",i(r.x),",",i(r.y),",",i(k.x),",",i(k.y))}else if(f.type=="at"||f.type=="wa"){b.push(" ",f.type," ");var k=this.b(f.x,f.y),s=this.b(f.xStart,f.yStart),t=this.b(f.xEnd,f.yEnd);b.push(i(k.x-this.d*f.radius),",",i(k.y-this.e*f.radius)," ",i(k.x+this.d*f.radius),",",i(k.y+this.e*f.radius)," ",i(s.x),",",i(s.y)," ",i(t.x),",",i(t.y))}if(k){if(l.x==null||k.x<l.x){l.x=k.x}if(n.x==null||k.x>n.x){n.x=k.x}if(l.y==
+null||k.y<l.y){l.y=k.y}if(n.y==null||k.y>n.y){n.y=k.y}}}b.push(' ">');if(typeof this.fillStyle=="object"){var v={x:"50%",y:"50%"},w=n.x-l.x,x=n.y-l.y,p=w>x?w:x;v.x=i(this.fillStyle.i.x/w*100+50)+"%";v.y=i(this.fillStyle.i.y/x*100+50)+"%";var y=[];if(this.fillStyle.p=="gradientradial"){var z=this.fillStyle.n/p*100,B=this.fillStyle.o/p*100-z}else{var z=0,B=100}var C={offset:null,color:null},D={offset:null,color:null};this.fillStyle.h.sort(function(T,U){return T.offset-U.offset});for(var o=0;o<this.fillStyle.h.length;o++){var u=
+this.fillStyle.h[o];y.push(u.offset*B+z,"% ",u.color,",");if(u.offset>C.offset||C.offset==null){C.offset=u.offset;C.color=u.color}if(u.offset<D.offset||D.offset==null){D.offset=u.offset;D.color=u.color}}y.pop();b.push("<g_vml_:fill",' color="',D.color,'"',' color2="',C.color,'"',' type="',this.fillStyle.p,'"',' focusposition="',v.x,", ",v.y,'"',' colors="',y.join(""),'"',' opacity="',e,'" />')}else if(a){b.push('<g_vml_:fill color="',d,'" opacity="',e,'" />')}else{b.push("<g_vml_:stroke",' opacity="',
+e,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',S(this.lineCap),'"',' weight="',this.lineWidth,'px"',' color="',d,'" />')}b.push("</g_vml_:shape>");this.j.insertAdjacentHTML("beforeEnd",b.join(""));this.c=[]};j.fill=function(){this.stroke(true)};j.closePath=function(){this.c.push({type:"close"})};j.b=function(a,b){return{x:m*(a*this.a[0][0]+b*this.a[1][0]+this.a[2][0])-A,y:m*(a*this.a[0][1]+b*this.a[1][1]+this.a[2][1])-A}};j.save=function(){var a={};N(this,a);
+this.k.push(a);this.m.push(this.a);this.a=G(J(),this.a)};j.restore=function(){N(this.k.pop(),this);this.a=this.m.pop()};j.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];this.a=G(c,this.a)};j.rotate=function(a){var b=M(a),c=L(a),d=[[b,c,0],[-c,b,0],[0,0,1]];this.a=G(d,this.a)};j.scale=function(a,b){this.d*=a;this.e*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];this.a=G(c,this.a)};j.clip=function(){};j.arcTo=function(){};j.createPattern=function(){return new P};function H(a){this.p=a;this.n=0;this.o=
+0;this.h=[];this.i={x:0,y:0}}H.prototype.addColorStop=function(a,b){b=O(b);this.h.push({offset:1-a,color:b})};function P(){}G_vmlCanvasManager=Q;CanvasRenderingContext2D=K;CanvasGradient=H;CanvasPattern=P})()};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/static/graph.js	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,137 @@
+// branch_renderer.js - Rendering of branch DAGs on the client side
+//
+// Copyright 2008 Dirkjan Ochtman <dirkjan AT ochtman DOT nl>
+// Copyright 2006 Alexander Schremmer <alex AT alexanderweb DOT de>
+//
+// derived from code written by Scott James Remnant <scott@ubuntu.com>
+// Copyright 2005 Canonical Ltd.
+//
+// This software may be used and distributed according to the terms
+// of the GNU General Public License, incorporated herein by reference.
+
+var colors = [
+	[ 1.0, 0.0, 0.0 ],
+	[ 1.0, 1.0, 0.0 ],
+	[ 0.0, 1.0, 0.0 ],
+	[ 0.0, 1.0, 1.0 ],
+	[ 0.0, 0.0, 1.0 ],
+	[ 1.0, 0.0, 1.0 ]
+];
+
+function Graph() {
+	
+	this.canvas = document.getElementById('graph');
+	if (navigator.userAgent.indexOf('MSIE') >= 0) this.canvas = window.G_vmlCanvasManager.initElement(this.canvas);
+	this.ctx = this.canvas.getContext('2d');
+	this.ctx.strokeStyle = 'rgb(0, 0, 0)';
+	this.ctx.fillStyle = 'rgb(0, 0, 0)';
+	this.cur = [0, 0];
+	this.line_width = 3;
+	this.bg = [0, 4];
+	this.cell = [2, 0];
+	this.columns = 0;
+	this.revlink = '';
+	
+	this.scale = function(height) {
+		this.bg_height = height;
+		this.box_size = Math.floor(this.bg_height / 1.2);
+		this.cell_height = this.box_size;
+	}
+	
+	function colorPart(num) {
+		num *= 255
+		num = num < 0 ? 0 : num;
+		num = num > 255 ? 255 : num;
+		var digits = Math.round(num).toString(16);
+		if (num < 16) {
+			return '0' + digits;
+		} else {
+			return digits;
+		}
+	}
+
+	this.setColor = function(color, bg, fg) {
+		
+		// Set the colour.
+		//
+		// Picks a distinct colour based on an internal wheel; the bg
+		// parameter provides the value that should be assigned to the 'zero'
+		// colours and the fg parameter provides the multiplier that should be
+		// applied to the foreground colours.
+		
+		color %= colors.length;
+		var red = (colors[color][0] * fg) || bg;
+		var green = (colors[color][1] * fg) || bg;
+		var blue = (colors[color][2] * fg) || bg;
+		red = Math.round(red * 255);
+		green = Math.round(green * 255);
+		blue = Math.round(blue * 255);
+		var s = 'rgb(' + red + ', ' + green + ', ' + blue + ')';
+		this.ctx.strokeStyle = s;
+		this.ctx.fillStyle = s;
+		return s;
+		
+	}
+
+	this.render = function(data) {
+		
+		var backgrounds = '';
+		var nodedata = '';
+		
+		for (var i in data) {
+			
+			var parity = i % 2;
+			this.cell[1] += this.bg_height;
+			this.bg[1] += this.bg_height;
+			
+			var cur = data[i];
+			var node = cur[1];
+			var edges = cur[2];
+			var fold = false;
+			
+			for (var j in edges) {
+				
+				line = edges[j];
+				start = line[0];
+				end = line[1];
+				color = line[2];
+
+				if (end > this.columns || start > this.columns) {
+					this.columns += 1;
+				}
+				
+				if (start == this.columns && start > end) {
+					var fold = true;
+				}
+				
+				x0 = this.cell[0] + this.box_size * start + this.box_size / 2;
+				y0 = this.bg[1] - this.bg_height / 2;
+				x1 = this.cell[0] + this.box_size * end + this.box_size / 2;
+				y1 = this.bg[1] + this.bg_height / 2;
+				
+				this.edge(x0, y0, x1, y1, color);
+				
+			}
+			
+			// Draw the revision node in the right column
+			
+			column = node[0]
+			color = node[1]
+			
+			radius = this.box_size / 8;
+			x = this.cell[0] + this.box_size * column + this.box_size / 2;
+			y = this.bg[1] - this.bg_height / 2;
+			var add = this.vertex(x, y, color, parity, cur);
+			backgrounds += add[0];
+			nodedata += add[1];
+			
+			if (fold) this.columns -= 1;
+			
+		}
+		
+		document.getElementById('nodebgs').innerHTML += backgrounds;
+		document.getElementById('graphnodes').innerHTML += nodedata;
+		
+	}
+
+}
Binary file mercurial-tests/testData/bin/Templates/static/hgicon.png has changed
Binary file mercurial-tests/testData/bin/Templates/static/hglogo.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/static/style-coal.css	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,265 @@
+body {
+  margin: 0;
+  padding: 0;
+  background: black url(background.png) repeat-x;
+  font-family: sans-serif;
+}
+
+.container {
+  padding-right: 150px;
+}
+
+.main {
+  position: relative;
+  background: white;
+  padding: 2em;
+  border-right: 15px solid black;
+  border-bottom: 15px solid black;
+}
+
+#.main {
+  width: 98%;
+}
+
+.overflow {
+  width: 100%;
+  overflow: auto;
+}
+
+.menu {
+  background: #999;
+  padding: 10px;
+  width: 75px;
+  margin: 0;
+  font-size: 80%;
+  text-align: left;
+  position: fixed;
+  top: 27px;
+  left: auto;
+  right: 27px;
+}
+
+#.menu {
+  position: absolute !important;
+  top:expression(eval(document.body.scrollTop + 27));
+}
+
+.menu ul {
+  list-style: none;
+  padding: 0;
+  margin: 10px 0 0 0;
+}
+
+.menu li {
+  margin-bottom: 3px;
+  padding: 2px 4px;
+  background: white;
+  color: black;
+  font-weight: normal;
+}
+
+.menu li.active {
+  background: black;
+  color: white;
+}
+
+.menu img {
+  width: 75px;
+  height: 90px;
+  border: 0;
+}
+
+.menu a { color: black; display: block; }
+
+.search {
+  position: absolute;
+  top: .7em;
+  right: 2em;
+}
+
+form.search div#hint {
+  display: none;
+  position: absolute;
+  top: 40px;
+  right: 0px;
+  width: 190px;
+  padding: 5px;
+  background: #ffc;
+  font-size: 70%;
+  border: 1px solid yellow;
+  -moz-border-radius: 5px; /* this works only in camino/firefox */
+  -webkit-border-radius: 5px; /* this is just for Safari */
+}
+
+form.search:hover div#hint { display: block; }
+
+a { text-decoration:none; }
+.age { white-space:nowrap; }
+.date { white-space:nowrap; }
+.indexlinks { white-space:nowrap; }
+.parity0 { background-color: #f0f0f0; }
+.parity1 { background-color: white; }
+.plusline { color: green; }
+.minusline { color: #dc143c; } /* crimson */
+.atline { color: purple; }
+
+.navigate {
+  text-align: right;
+  font-size: 60%;
+  margin: 1em 0;
+}
+
+.tag {
+  color: #999;
+  font-size: 70%;
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+.branchhead {
+  color: #000;
+  font-size: 80%;
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+ul#graphnodes .branchhead {
+  font-size: 75%;
+}
+
+.branchname {
+  color: #000;
+  font-size: 60%; 
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+h3 .branchname {
+  font-size: 80%;
+}
+
+/* Common */
+pre { margin: 0; }
+
+h2 { font-size: 120%; border-bottom: 1px solid #999; }
+h2 a { color: #000; }
+h3 {
+  margin-top: -.7em;
+  font-size: 100%;
+}
+
+/* log and tags tables */
+.bigtable {
+  border-bottom: 1px solid #999;
+  border-collapse: collapse;
+  font-size: 90%;
+  width: 100%;
+  font-weight: normal;
+  text-align: left;
+}
+
+.bigtable td {
+  vertical-align: top;
+}
+
+.bigtable th {
+  padding: 1px 4px;
+  border-bottom: 1px solid #999;
+}
+.bigtable tr { border: none; }
+.bigtable .age { width: 6em; }
+.bigtable .author { width: 12em; }
+.bigtable .description { }
+.bigtable .node { width: 5em; font-family: monospace;}
+.bigtable .lineno { width: 2em; text-align: right;}
+.bigtable .lineno a { color: #999; font-size: smaller; font-family: monospace;}
+.bigtable .permissions { width: 8em; text-align: left;}
+.bigtable .size { width: 5em; text-align: right; }
+.bigtable .annotate { text-align: right; }
+.bigtable td.annotate { font-size: smaller; }
+.bigtable td.source { font-size: inherit; }
+
+.source, .sourcefirst, .sourcelast {
+  font-family: monospace;
+  white-space: pre;
+  padding: 1px 4px;
+  font-size: 90%;
+}
+.sourcefirst { border-bottom: 1px solid #999; font-weight: bold; }
+.sourcelast { border-top: 1px solid #999; }
+.source a { color: #999; font-size: smaller; font-family: monospace;}
+.bottomline { border-bottom: 1px solid #999; }
+
+.fileline { font-family: monospace; }
+.fileline img { border: 0; }
+
+.tagEntry .closed { color: #99f; }
+
+/* Changeset entry */
+#changesetEntry {
+  border-collapse: collapse;
+  font-size: 90%;
+  width: 100%;
+  margin-bottom: 1em;
+}
+
+#changesetEntry th {
+  padding: 1px 4px;
+  width: 4em;
+  text-align: right;
+  font-weight: normal;
+  color: #999;
+  margin-right: .5em;
+  vertical-align: top;
+}
+
+div.description {
+  border-left: 3px solid #999;
+  margin: 1em 0 1em 0;
+  padding: .3em;
+}
+
+/* Graph */
+div#wrapper {
+	position: relative;
+	border-top: 1px solid black;
+	border-bottom: 1px solid black;
+	margin: 0;
+	padding: 0;
+}
+
+canvas {
+	position: absolute;
+	z-index: 5;
+	top: -0.7em;
+	margin: 0;
+}
+
+ul#graphnodes {
+	position: absolute;
+	z-index: 10;
+	top: -1.0em;
+	list-style: none inside none;
+	padding: 0;
+}
+
+ul#nodebgs {
+	list-style: none inside none;
+	padding: 0;
+	margin: 0;
+	top: -0.7em;
+}
+
+ul#graphnodes li, ul#nodebgs li {
+	height: 39px;
+}
+
+ul#graphnodes li .info {
+	display: block;
+	font-size: 70%;
+	position: relative;
+	top: -3px;
+}
--- a/mercurial-tests/testData/bin/Templates/static/style-gitweb.css	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/static/style-gitweb.css	Wed Dec 09 11:14:30 2009 +0300
@@ -79,3 +79,45 @@
 	background-color: #d5dde6;
 	border-color: #e3ecf4 #9398f4 #9398f4 #e3ecf4;
 }
+
+/* Graph */
+div#wrapper {
+	position: relative;
+	margin: 0;
+	padding: 0;
+	margin-top: 3px;
+}
+
+canvas {
+	position: absolute;
+	z-index: 5;
+	top: -0.9em;
+	margin: 0;
+}
+
+ul#nodebgs {
+	list-style: none inside none;
+	padding: 0;
+	margin: 0;
+	top: -0.7em;
+}
+
+ul#graphnodes li, ul#nodebgs li {
+	height: 39px;
+}
+
+ul#graphnodes {
+	position: absolute;
+	z-index: 10;
+	top: -0.8em;
+	list-style: none inside none;
+	padding: 0;
+}
+
+ul#graphnodes li .info {
+	display: block;
+	font-size: 100%;
+	position: relative;
+	top: -3px;
+	font-style: italic;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/static/style-monoblue.css	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,472 @@
+/*** Initial Settings ***/
+* {
+  margin: 0;
+  padding: 0;
+  font-weight: normal;
+  font-style: normal;
+}
+
+html {
+  font-size: 100%;
+  font-family: sans-serif;
+}
+
+body {
+  font-size: 77%;
+  margin: 15px 50px;
+  background: #4B4B4C;
+}
+
+a {
+  color:#0000cc;
+  text-decoration: none;
+}
+/*** end of Initial Settings ***/
+
+
+/** common settings **/
+div#container {
+  background: #FFFFFF;
+  position: relative;
+  color: #666;
+}
+
+div.page-header {
+  padding: 50px 20px 0;
+  background: #006699 top left repeat-x;
+  position: relative;
+}
+  div.page-header h1 {
+    margin: 10px 0 30px;
+    font-size: 1.8em;
+    font-weight: bold;
+    font-family: osaka,'MS P Gothic', Georgia, serif;
+    letter-spacing: 1px;
+    color: #DDD;
+  }
+  div.page-header h1 a {
+    font-weight: bold;
+    color: #FFF;
+  }
+  div.page-header a {
+    text-decoration: none;
+  }
+
+  div.page-header form {
+    position: absolute;
+    margin-bottom: 2px;
+    bottom: 0;
+    right: 20px;
+  }
+  div.page-header form label {
+    color: #DDD;
+  }
+  div.page-header form input {
+    padding: 2px;
+    border: solid 1px #DDD;
+  }
+  div.page-header form dl {
+    overflow: hidden;
+  }
+  div.page-header form dl dt {
+    font-size: 1.2em;
+  }
+  div.page-header form dl dt,
+  div.page-header form dl dd {
+    margin: 0 0 0 5px;
+    float: left;
+    height: 24px;
+    line-height: 20px;
+  }
+
+  ul.page-nav {
+    margin: 10px 0 0 0;
+    list-style-type: none;
+    overflow: hidden;
+    width: 800px;
+  }
+    ul.page-nav li {
+      margin: 0 2px 0 0;
+      float: left;
+      width: 80px;
+      height: 24px;
+      font-size: 1.1em;
+      line-height: 24px;
+      text-align: center;
+    }
+    ul.page-nav li.current {
+      background: #FFF;
+    }
+    ul.page-nav li a {
+      height: 24px;
+      color: #666;
+      background: #DDD;
+      display: block;
+      text-decoration: none;
+    }
+    ul.page-nav li a:hover {
+      color:#333;
+      background: #FFF;
+    }
+
+ul.submenu {
+  margin: 10px 0 -10px 20px;
+  list-style-type: none;
+}
+ul.submenu li {
+  margin: 0 10px 0 0;
+  font-size: 1.2em;
+  display: inline;
+}
+
+h2 {
+  margin: 20px 0 10px;
+  height: 30px;
+  line-height: 30px;
+  text-indent: 20px;
+  background: #FFF;
+  font-size: 1.2em;
+  border-top: dotted 1px #D5E1E6;
+  font-weight: bold;
+}
+h2.no-link {
+  color:#006699;
+}
+h2.no-border {
+  color: #FFF;
+  background: #006699;
+  border: 0;
+}
+h2 a {
+  font-weight:bold;
+  color:#006699;
+}
+
+div.page-path {
+  text-align: right;
+  padding: 20px 30px 10px 0;
+  border:solid #d9d8d1;
+  border-width:0px 0px 1px;
+  font-size: 1.2em;
+}
+
+div.page-footer {
+  margin: 50px 0 0;
+  position: relative;
+}
+  div.page-footer p {
+    position: relative;
+    left: 20px;
+    bottom: 5px;
+    font-size: 1.2em;
+  }
+
+  ul.rss-logo {
+    position: absolute;
+    top: -10px;
+    right: 20px;
+    height: 20px;
+    list-style-type: none;
+  }
+  ul.rss-logo li {
+    display: inline;
+  }
+  ul.rss-logo li a {
+    padding: 3px 6px;
+    line-height: 10px;
+    border:1px solid;
+    border-color:#fcc7a5 #7d3302 #3e1a01 #ff954e;
+    color:#ffffff;
+    background-color:#ff6600;
+    font-weight:bold;
+    font-family:sans-serif;
+    font-size:10px;
+    text-align:center;
+    text-decoration:none;
+  }
+  div.rss-logo li a:hover {
+    background-color:#ee5500;
+  }
+
+p.normal {
+  margin: 20px 0 20px 30px;
+  font-size: 1.2em;
+}
+
+table {
+  margin: 10px 0 0 20px;
+  width: 95%;
+  border-collapse: collapse;
+}
+table tr td {
+  font-size: 1.1em;
+}
+table tr td.nowrap {
+  white-space: nowrap;
+}
+/*
+table tr.parity0:hover,
+table tr.parity1:hover {
+  background: #D5E1E6;
+}
+*/
+table tr.parity0 {
+  background: #F1F6F7;
+}
+table tr.parity1 {
+  background: #FFFFFF;
+}
+table tr td {
+  padding: 5px 5px;
+}
+table.annotated tr td {
+  padding: 0px 5px;
+}
+
+span.logtags span {
+  padding: 2px 6px;
+  font-weight: normal;
+  font-size: 11px;
+  border: 1px solid;
+  background-color: #ffaaff;
+  border-color: #ffccff #ff00ee #ff00ee #ffccff;
+}
+span.logtags span.tagtag {
+  background-color: #ffffaa;
+  border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
+}
+span.logtags span.branchtag {
+  background-color: #aaffaa;
+  border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
+}
+span.logtags span.inbranchtag {
+  background-color: #d5dde6;
+  border-color: #e3ecf4 #9398f4 #9398f4 #e3ecf4;
+}
+
+div.diff pre {
+  margin: 10px 0 0 0;
+}
+div.diff pre span {
+  font-family: monospace;
+  white-space: pre;
+  font-size: 1.2em;
+  padding: 3px 0;
+}
+td.source {
+  white-space: pre;
+  font-family: monospace;
+  margin: 10px 30px 0;
+  font-size: 1.2em;
+  font-family: monospace;
+}
+  div.source div.parity0,
+  div.source div.parity1 {
+    padding: 1px;
+    font-size: 1.2em;
+  }
+  div.source div.parity0 {
+    background: #F1F6F7;
+  }
+  div.source div.parity1 {
+    background: #FFFFFF;
+  }
+div.parity0:hover,
+div.parity1:hover {
+  background: #D5E1E6;
+}
+.linenr {
+  color: #999;
+  text-align: right;
+}
+.lineno {
+  text-align: right;
+}
+.lineno a {
+  color: #999;
+}
+td.linenr {
+  width: 60px;
+}
+
+div#powered-by {
+  position: absolute;
+  width: 75px;
+  top: 15px;
+  right: 20px;
+  font-size: 1.2em;
+}
+div#powered-by a {
+  color: #EEE;
+  text-decoration: none;
+}
+div#powered-by a:hover {
+  text-decoration: underline;
+}
+/*
+div#monoblue-corner-top-left {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 10px;
+  height: 10px;
+  background: url(./monoblue-corner.png) top left no-repeat !important;
+  background: none;
+}
+div#monoblue-corner-top-right {
+  position: absolute;
+  top: 0;
+  right: 0;
+  width: 10px;
+  height: 10px;
+  background: url(./monoblue-corner.png) top right no-repeat !important;
+  background: none;
+}
+div#monoblue-corner-bottom-left {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  width: 10px;
+  height: 10px;
+  background: url(./monoblue-corner.png) bottom left no-repeat !important;
+  background: none;
+}
+div#monoblue-corner-bottom-right {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  width: 10px;
+  height: 10px;
+  background: url(./monoblue-corner.png) bottom right no-repeat !important;
+  background: none;
+}
+*/
+/** end of common settings **/
+
+/** summary **/
+dl.overview {
+  margin: 0 0 0 30px;
+  font-size: 1.1em;
+  overflow: hidden;
+}
+  dl.overview dt,
+  dl.overview dd {
+    margin: 5px 0;
+    float: left;
+  }
+  dl.overview dt {
+    clear: left;
+    font-weight: bold;
+    width: 150px;
+  }
+/** end of summary **/
+
+/** chagelog **/
+h3.changelog {
+  margin: 20px 0 5px 30px;
+  padding: 0 0 2px;
+  font-size: 1.4em;
+  border-bottom: dotted 1px #D5E1E6;
+}
+ul.changelog-entry {
+  margin: 0 0 10px 30px;
+  list-style-type: none;
+  position: relative;
+}
+ul.changelog-entry li span.revdate {
+  font-size: 1.1em;
+}
+ul.changelog-entry li.age {
+  position: absolute;
+  top: -25px;
+  right: 10px;
+  font-size: 1.4em;
+  color: #CCC;
+  font-weight: bold;
+  font-style: italic;
+}
+ul.changelog-entry li span.name {
+  font-size: 1.2em;
+  font-weight: bold;
+}
+ul.changelog-entry li.description {
+  margin: 10px 0 0;
+  font-size: 1.1em;
+}
+/** end of changelog **/
+
+/** file **/
+p.files {
+  margin: 0 0 0 20px;
+  font-size: 2.0em;
+  font-weight: bold;
+}
+/** end of file **/
+
+/** changeset **/
+h3.changeset {
+  margin: 20px 0 5px 20px;
+  padding: 0 0 2px;
+  font-size: 1.6em;
+  border-bottom: dotted 1px #D5E1E6;
+}
+p.changeset-age {
+  position: relative;
+}
+p.changeset-age span {
+  position: absolute;
+  top: -25px;
+  right: 10px;
+  font-size: 1.4em;
+  color: #CCC;
+  font-weight: bold;
+  font-style: italic;
+}
+p.description {
+  margin: 10px 30px 0 30px;
+  padding: 10px;
+  border: solid 1px #CCC;
+  font-size: 1.2em;
+}
+/** end of changeset **/
+
+/** canvas **/
+div#wrapper {
+	position: relative;
+    font-size: 1.2em;
+}
+
+canvas {
+	position: absolute;
+	z-index: 5;
+	top: -0.7em;
+}
+
+ul#nodebgs li.parity0 {
+    background: #F1F6F7;
+}
+
+ul#nodebgs li.parity1 {
+    background: #FFFFFF;
+}
+
+ul#graphnodes {
+	position: absolute;
+	z-index: 10;
+	top: 7px;
+	list-style: none inside none;
+}
+
+ul#nodebgs {
+	list-style: none inside none;
+}
+
+ul#graphnodes li, ul#nodebgs li {
+	height: 39px;
+}
+
+ul#graphnodes li .info {
+	display: block;
+	position: relative;
+}
+/** end of canvas **/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bin/Templates/static/style-paper.css	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,254 @@
+body {
+  margin: 0;
+  padding: 0;
+  background: white;
+  font-family: sans-serif;
+}
+
+.container {
+  padding-left: 115px;
+}
+
+.main {
+  position: relative;
+  background: white;
+  padding: 2em 2em 2em 0;
+}
+
+#.main {
+  width: 98%;
+}
+
+.overflow {
+  width: 100%;
+  overflow: auto;
+}
+
+.menu {
+  width: 90px;
+  margin: 0;
+  font-size: 80%;
+  text-align: left;
+  position: absolute;
+  top: 20px;
+  left: 20px;
+  right: auto;
+}
+
+.menu ul {
+  list-style: none;
+  padding: 0;
+  margin: 10px 0 0 0;
+  border-left: 2px solid #999;
+}
+
+.menu li {
+  margin-bottom: 3px;
+  padding: 2px 4px;
+  background: white;
+  color: black;
+  font-weight: normal;
+}
+
+.menu li.active {
+  font-weight: bold;
+}
+
+.menu img {
+  width: 75px;
+  height: 90px;
+  border: 0;
+}
+
+.menu a { color: black; display: block; }
+
+.search {
+  position: absolute;
+  top: .7em;
+  right: 2em;
+}
+
+form.search div#hint {
+  display: none;
+  position: absolute;
+  top: 40px;
+  right: 0px;
+  width: 190px;
+  padding: 5px;
+  background: #ffc;
+  font-size: 70%;
+  border: 1px solid yellow;
+  -moz-border-radius: 5px; /* this works only in camino/firefox */
+  -webkit-border-radius: 5px; /* this is just for Safari */
+}
+
+form.search:hover div#hint { display: block; }
+
+a { text-decoration:none; }
+.age { white-space:nowrap; }
+.date { white-space:nowrap; }
+.indexlinks { white-space:nowrap; }
+.parity0 { background-color: #f0f0f0; }
+.parity1 { background-color: white; }
+.plusline { color: green; }
+.minusline { color: #dc143c; } /* crimson */
+.atline { color: purple; }
+
+.navigate {
+  text-align: right;
+  font-size: 60%;
+  margin: 1em 0;
+}
+
+.tag {
+  color: #999;
+  font-size: 70%;
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+.branchhead {
+  color: #000;
+  font-size: 80%;
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+ul#graphnodes .branchhead {
+  font-size: 75%;
+}
+
+.branchname {
+  color: #000;
+  font-size: 60%; 
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+h3 .branchname {
+  font-size: 80%;
+}
+
+/* Common */
+pre { margin: 0; }
+
+h2 { font-size: 120%; border-bottom: 1px solid #999; }
+h2 a { color: #000; }
+h3 {
+  margin-top: -.7em;
+  font-size: 100%;
+}
+
+/* log and tags tables */
+.bigtable {
+  border-bottom: 1px solid #999;
+  border-collapse: collapse;
+  font-size: 90%;
+  width: 100%;
+  font-weight: normal;
+  text-align: left;
+}
+
+.bigtable td {
+  vertical-align: top;
+}
+
+.bigtable th {
+  padding: 1px 4px;
+  border-bottom: 1px solid #999;
+}
+.bigtable tr { border: none; }
+.bigtable .age { width: 7em; }
+.bigtable .author { width: 12em; }
+.bigtable .description { }
+.bigtable .node { width: 5em; font-family: monospace;}
+.bigtable .permissions { width: 8em; text-align: left;}
+.bigtable .size { width: 5em; text-align: right; }
+.bigtable .annotate { text-align: right; }
+.bigtable td.annotate { font-size: smaller; }
+.bigtable td.source { font-size: inherit; }
+
+.source, .sourcefirst, .sourcelast {
+  font-family: monospace;
+  white-space: pre;
+  padding: 1px 4px;
+  font-size: 90%;
+}
+.sourcefirst { border-bottom: 1px solid #999; font-weight: bold; }
+.sourcelast { border-top: 1px solid #999; }
+.source a { color: #999; font-size: smaller; font-family: monospace;}
+.bottomline { border-bottom: 1px solid #999; }
+
+.fileline { font-family: monospace; }
+.fileline img { border: 0; }
+
+.tagEntry .closed { color: #99f; }
+
+/* Changeset entry */
+#changesetEntry {
+  border-collapse: collapse;
+  font-size: 90%;
+  width: 100%;
+  margin-bottom: 1em;
+}
+
+#changesetEntry th {
+  padding: 1px 4px;
+  width: 4em;
+  text-align: right;
+  font-weight: normal;
+  color: #999;
+  margin-right: .5em;
+  vertical-align: top;
+}
+
+div.description {
+  border-left: 2px solid #999;
+  margin: 1em 0 1em 0;
+  padding: .3em;
+}
+
+/* Graph */
+div#wrapper {
+	position: relative;
+	border-top: 1px solid black;
+	border-bottom: 1px solid black;
+	margin: 0;
+	padding: 0;
+}
+
+canvas {
+	position: absolute;
+	z-index: 5;
+	top: -0.7em;
+	margin: 0;
+}
+
+ul#graphnodes {
+	position: absolute;
+	z-index: 10;
+	top: -1.0em;
+	list-style: none inside none;
+	padding: 0;
+}
+
+ul#nodebgs {
+	list-style: none inside none;
+	padding: 0;
+	margin: 0;
+	top: -0.7em;
+}
+
+ul#graphnodes li, ul#nodebgs li {
+	height: 39px;
+}
+
+ul#graphnodes li .info {
+	display: block;
+	font-size: 70%;
+	position: relative;
+	top: -3px;
+}
--- a/mercurial-tests/testData/bin/Templates/static/style.css	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial-tests/testData/bin/Templates/static/style.css	Wed Dec 09 11:14:30 2009 +0300
@@ -2,16 +2,16 @@
 .age { white-space:nowrap; }
 .date { white-space:nowrap; }
 .indexlinks { white-space:nowrap; }
-.parity0 { background-color: #dddddd; }
-.parity1 { background-color: #eeeeee; }
-.lineno { width: 60px; color: #aaaaaa; font-size: smaller;
-          text-align: right; padding-right:1em; }
+.parity0 { background-color: #ddd; }
+.parity1 { background-color: #eee; }
+.lineno { width: 60px; color: #aaa; font-size: smaller;
+          text-align: right; }
 .plusline { color: green; }
 .minusline { color: red; }
 .atline { color: purple; }
 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
 .buttons a {
-  background-color: #666666;
+  background-color: #666;
   padding: 2pt;
   color: white;
   font-family: sans;
@@ -25,7 +25,7 @@
 }
 
 .metatag {
-  background-color: #888888;
+  background-color: #888;
   color: white;
   text-align: right;
 }
@@ -64,3 +64,42 @@
 #filediffEntry { }
 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
 
+/* Graph */
+div#wrapper {
+	position: relative;
+	margin: 0;
+	padding: 0;
+}
+
+canvas {
+	position: absolute;
+	z-index: 5;
+	top: -0.6em;
+	margin: 0;
+}
+
+ul#nodebgs {
+	list-style: none inside none;
+	padding: 0;
+	margin: 0;
+	top: -0.7em;
+}
+
+ul#graphnodes li, ul#nodebgs li {
+	height: 39px;
+}
+
+ul#graphnodes {
+	position: absolute;
+	z-index: 10;
+	top: -0.85em;
+	list-style: none inside none;
+	padding: 0;
+}
+
+ul#graphnodes li .info {
+	display: block;
+	font-size: 70%;
+	position: relative;
+	top: -1px;
+}
Binary file mercurial-tests/testData/bin/hg.exe has changed
Binary file mercurial-tests/testData/bin/library.zip has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep1/hg/branch	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep1/hg/branchheads.cache	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,4 @@
+9babcf2d5705e64e85375516be4ede87baf9ce82 9
+b9deb9a1c6f43e8a3b9f7d12c1ec468352b4397e default
+04c3ae4c631244646c017d503be49fe62e9aea9c test_branch
+9babcf2d5705e64e85375516be4ede87baf9ce82 name with space
Binary file mercurial-tests/testData/rep1/hg/dirstate has changed
Binary file mercurial-tests/testData/rep1/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/rep1/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/rep1/hg/store/data/file.txt.i has changed
Binary file mercurial-tests/testData/rep1/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep1/hg/tags.cache	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,3 @@
+10 9c6a6b4aede0c48cd8b9942bbd932a8349145c67
+9 9babcf2d5705e64e85375516be4ede87baf9ce82
+
Binary file mercurial-tests/testData/rep1/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/rep2/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep2/hg/branch	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep2/hg/branchheads.cache	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,3 @@
+48177654181c50307bfb333f824126f54858cf53 11
+48177654181c50307bfb333f824126f54858cf53 default
+fc524efc2bc481e22365ab1452a41197060dbd9b test
Binary file mercurial-tests/testData/rep2/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep2/hg/requires	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,3 @@
+revlogv1
+store
+fncache
Binary file mercurial-tests/testData/rep2/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir1/file1.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir2/file2.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir3/file3.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir4/file4.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir4/file41.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir4/file42.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir4/file43.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir5/file5.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/dir6/file6.txt.i has changed
Binary file mercurial-tests/testData/rep2/hg/store/data/file.txt.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep2/hg/store/fncache	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,10 @@
+data/file.txt.i
+data/dir3/file3.txt.i
+data/dir1/file1.txt.i
+data/dir2/file2.txt.i
+data/dir4/file4.txt.i
+data/dir4/file41.txt.i
+data/dir4/file42.txt.i
+data/dir4/file43.txt.i
+data/dir5/file5.txt.i
+data/dir6/file6.txt.i
Binary file mercurial-tests/testData/rep2/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep2/hg/tags.cache	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,2 @@
+12 1e620196c4b6ee23219fb7bd460afde52b239805
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/rep2/hg/undo.branch	Wed Dec 09 11:14:30 2009 +0300
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
Binary file mercurial-tests/testData/rep2/hg/undo.dirstate has changed
--- a/mercurial.ipr	Wed Nov 25 00:46:31 2009 +0300
+++ b/mercurial.ipr	Wed Dec 09 11:14:30 2009 +0300
@@ -119,13 +119,6 @@
       <item index="4" class="java.lang.String" itemvalue="SERVER PROBLEM" />
     </list>
   </component>
-  <component name="JavacSettings">
-    <option name="DEBUGGING_INFO" value="true" />
-    <option name="GENERATE_NO_WARNINGS" value="false" />
-    <option name="DEPRECATION" value="true" />
-    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
-    <option name="MAXIMUM_HEAP_SIZE" value="128" />
-  </component>
   <component name="JavadocGenerationManager">
     <option name="OUTPUT_DIRECTORY" />
     <option name="OPTION_SCOPE" value="protected" />
@@ -328,13 +321,6 @@
       </value>
     </option>
   </component>
-  <component name="RmicSettings">
-    <option name="IS_EANABLED" value="false" />
-    <option name="DEBUGGING_INFO" value="true" />
-    <option name="GENERATE_NO_WARNINGS" value="false" />
-    <option name="GENERATE_IIOP_STUBS" value="false" />
-    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
-  </component>
   <component name="ScopeChooserConfigurable.UI">
     <option name="proportions">
       <SplitterProportionsDataImpl />