# HG changeset patch # User eugene.petrenko@gmail.com # Date 1380546685 -7200 # Node ID 5a40adf2ca9e68ad258a5d00e3fe551c61c05676 # Parent 3daa8e36f8f1d8b6a3669fa50543010f2dbe3317 implement CommitsInfoBuilder API diff -r 3daa8e36f8f1 -r 5a40adf2ca9e mercurial-server/src/META-INF/build-server-plugin-mercurial.xml --- a/mercurial-server/src/META-INF/build-server-plugin-mercurial.xml Mon Sep 30 15:11:01 2013 +0200 +++ b/mercurial-server/src/META-INF/build-server-plugin-mercurial.xml Mon Sep 30 15:11:25 2013 +0200 @@ -12,4 +12,6 @@ + + diff -r 3daa8e36f8f1 -r 5a40adf2ca9e mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCommitsInfoBuilderSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCommitsInfoBuilderSupport.java Mon Sep 30 15:11:25 2013 +0200 @@ -0,0 +1,82 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial; + +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ChangeSet; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ChangeSetRevision; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; +import jetbrains.buildServer.vcs.*; +import jetbrains.vcs.api.CommitInfo; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.command.LogCommand.ZERO_PARENT_ID; + +/** + * Created 30.09.13 13:05 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public class MercurialCommitsInfoBuilderSupport implements CommitsInfoBuilder, MercurialServerExtension { + private final MercurialVcsSupport mySupport; + private final HgVcsRootFactory myHgVcsRootFactory; + + public MercurialCommitsInfoBuilderSupport(@NotNull MercurialVcsSupport vcs, + @NotNull HgVcsRootFactory vcsRootFactory) { + vcs.addExtension(this); + mySupport = vcs; + myHgVcsRootFactory = vcsRootFactory; + } + + @NotNull + public List collectCommits(@NotNull VcsRoot root, + @NotNull CheckoutRules rules, + @NotNull RepositoryStateData headState) throws VcsException { + final HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); + final ServerHgRepo repo = mySupport.createRepo(hgRoot); + mySupport.syncRepository(hgRoot); + + final Map commitToBean = new HashMap(); + + //this could be implemented better with newer version of HG + //currently we have a process per head and next we merge commits via Java's in-memory map + for (String commitId : headState.getBranchRevisions().values()) { + commitToBean.putAll(processChanges(repo, commitId)); + } + + //collect tags info + Map tags = repo.tags().call(); + for (Map.Entry e : tags.entrySet()) { + CommitDataBean bean = commitToBean.get(e.getValue()); + if (bean != null) bean.addTag(e.getKey()); + } + + return new ArrayList(commitToBean.values()); + } + + @NotNull + private Map processChanges(@NotNull ServerHgRepo repo, @NotNull final String head) throws VcsException { + final List tip = repo.logNoFiles() + .fromRevision("0") + .toRevision(head) + .showCommitsFromAllBranches() + .call(); + + final Map result = new HashMap(); + for (ChangeSet set : tip) { + final CommitDataBean bean = new CommitDataBean(set.getId(), set.getFullVersion(), set.getTimestamp()); + for (ChangeSetRevision p : set.getParents()) { + final String commitId = p.getId(); + + if (ZERO_PARENT_ID.equals(commitId)) continue; + bean.addParentRevision(commitId); + } + bean.addBranch(set.getBranch()); + result.put(bean.getVersion(), bean); + } + + return result; + } +} diff -r 3daa8e36f8f1 -r 5a40adf2ca9e mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CommitsInfoBuilderSupportTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CommitsInfoBuilderSupportTest.java Mon Sep 30 15:11:25 2013 +0200 @@ -0,0 +1,87 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial; + +import jetbrains.buildServer.TestLogger; +import jetbrains.buildServer.util.CollectionsUtil; +import jetbrains.buildServer.vcs.CheckoutRules; +import jetbrains.buildServer.vcs.RepositoryStateData; +import jetbrains.buildServer.vcs.VcsException; +import jetbrains.buildServer.vcs.VcsRoot; +import jetbrains.vcs.api.CommitInfo; +import junit.framework.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot; + +/** + * Created 30.09.13 13:07 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public class CommitsInfoBuilderSupportTest extends BaseMercurialTestCase { + private File myRemoteRepo; + private MercurialVcsSupport myVcs; + private MercurialCommitsInfoBuilderSupport mySupport; + + @Override + @BeforeMethod + public void setUp() throws Exception { + super.setUp(); + ServerPluginConfig pluginConfig = new ServerPluginConfigBuilder() + .cachesDir(myTempFiles.createTempDir()) + .build(); + MercurialSupportBuilder mercurialBuilder = mercurialSupport().withConfig(pluginConfig); + myVcs = mercurialBuilder.build(); + mySupport = new MercurialCommitsInfoBuilderSupport(myVcs, mercurialBuilder.getHgRootFactory()); + myRemoteRepo = myTempFiles.createTempDir(); + copyRepository(new File("mercurial-tests/testData/rep2"), myRemoteRepo); + } + + @Test + public void simpleTest() throws IOException, VcsException { + TestLogger.enableMainAndVCSLoggerDebug(); + + VcsRoot root = vcsRoot().withUrl(myRemoteRepo).build(); + + final String v = "4780519e01aa"; ///30 + + final List commitInfos = mySupport.collectCommits(root, CheckoutRules.DEFAULT, RepositoryStateData.createVersionState("default", CollectionsUtil.asMap("default", v))); + Assert.assertFalse(commitInfos.isEmpty()); + + for (CommitInfo commitInfo : commitInfos) { + System.out.println(commitInfo); + } + + final Set branches = new TreeSet(); + final Set tags = new TreeSet(); + final Set commits = new TreeSet(); + final Set parents = new TreeSet(); + for (CommitInfo commitInfo : commitInfos) { + branches.addAll(commitInfo.getBranches()); + tags.addAll(commitInfo.getTags()); + + //commit should be returned once + Assert.assertTrue(commits.add(commitInfo.getVersion())); + parents.addAll(commitInfo.getParentRevisions()); + } + + Assert.assertEquals(branches, new TreeSet(Arrays.asList("default", "personal-branch", "test", "topic"))); + Assert.assertEquals(tags, new TreeSet(Arrays.asList("t1"))); + + //check all parent commits are included into the set + Assert.assertTrue(commits.containsAll(parents)); + + //head should be head + Assert.assertFalse(parents.contains(v)); + } + +}