Mercurial > hg > mercurial
changeset 703:3aff8caf7d60
add API to parse hg log --patch to recover .hgsub .hgsubstate for entire history
author | eugene.petrenko@jetbrains.com |
---|---|
date | Wed, 08 Jan 2014 16:37:57 +0100 |
parents | dc12842c40e0 |
children | 5ee94ee69b29 |
files | mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LoadSubstatesCommand.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMountPointsSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMountPointsSupportTest.java |
diffstat | 4 files changed, 219 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LoadSubstatesCommand.java Wed Jan 08 16:37:57 2014 +0100 @@ -0,0 +1,83 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; + +import com.intellij.openapi.diagnostic.Logger; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.diff.*; +import jetbrains.buildServer.util.StringUtil; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.*; + +/** + * Created 03.01.14 14:53 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public class LoadSubstatesCommand extends VcsRootCommand { + private static final Logger LOG = Logger.getInstance(LoadSubstatesCommand.class.getName()); + + public LoadSubstatesCommand(@NotNull final CommandSettings commandSettings, + @NotNull final String hgPath, + @NotNull final File workingDir, + @NotNull final AuthSettings authSettings) { + super(commandSettings, hgPath, workingDir, authSettings); + } + + @NotNull + private Set<String> cat(@NotNull final String commit, + @NotNull final String file) throws VcsException { + final MercurialCommandLine cli = createCommandLine(); + cli.addParameter("cat"); + cli.addParameter("--rev"); + cli.addParameter(commit); + cli.addParameter(file); + + final CommandResult res = runCommand(cli); + return new LinkedHashSet<String>(Arrays.asList(StringUtil.splitByLines(res.getStdout()))); + } + + public void call(@NotNull final ContentProcessor consumer) throws VcsException { + final MercurialCommandLine cli = createCommandLine(); + cli.addParameter("log"); + cli.addParameter("--template=" + DiffParser.COMMITS_SEPARATOR + " {node|short} {p1node|short} {p2node|short}\\n"); + cli.addParameter("--patch"); + cli.addParameter(".hgsubstate"); + cli.addParameter(".hgsub"); + + CommandResult res = runCommand(cli); + final String output = res.getStdout(); + + //TODO: reverse patches stream so to minimize used memory for changes graph + + final DiffTree diff = new DiffTree() { + @NotNull + @Override + protected DiffFileTree createDiffFileTree(@NotNull final String file) { + return new DiffFileTree() { + @Override + protected void fetchContents(@NotNull List<String> commits, @NotNull Map<String, Set<String>> commitToLines) throws VcsException { + for (String commit : commits) { + LOG.debug("Fetching content for " + file + " @ " + commit + "..."); + commitToLines.put(commit, cat(commit, file)); + } + } + }; + } + }; + DiffParser.parse(lines(output), diff.processor()); + diff.processDiffs(consumer); + } + + private LinesIterator lines(@NotNull final String output) { + return new LinesIterator() { + final StringTokenizer st = new StringTokenizer(output, "\r\n"); + @Nullable + public String nextLine() { + if (st.hasMoreTokens()) return st.nextToken(); + return null; + } + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMountPointsSupport.java Wed Jan 08 16:37:57 2014 +0100 @@ -0,0 +1,50 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial; + +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.diff.ContentProcessor; +import jetbrains.buildServer.vcs.CheckoutRules; +import jetbrains.buildServer.vcs.VcsException; +import jetbrains.buildServer.vcs.VcsRoot; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * Created 03.01.14 13:57 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +public class MercurialMountPointsSupport implements MercurialServerExtension { + private final MercurialVcsSupport mySupport; + private final HgVcsRootFactory myHgVcsRootFactory; + + public MercurialMountPointsSupport(@NotNull MercurialVcsSupport vcs, + @NotNull HgVcsRootFactory vcsRootFactory) { + vcs.addExtension(this); + mySupport = vcs; + myHgVcsRootFactory = vcsRootFactory; + } + + + public void collectMountPoints(@NotNull final VcsRoot root, + @NotNull final CheckoutRules rules, + @NotNull final Object consumer) throws VcsException { + + final HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); + final ServerHgRepo repo = mySupport.createRepo(hgRoot); + + mySupport.syncRepository(hgRoot); + + repo.loadSubstates(new ContentProcessor() { + public void processContent(@NotNull String commit, @NotNull String file, @NotNull Collection<String> lines) { + System.out.println(commit + " " + file + "\n"); + for (String line : lines) { + System.out.println(" " + line); + } + System.out.println(); + } + }); + + } + +}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java Tue Jan 07 15:57:42 2014 +0100 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java Wed Jan 08 16:37:57 2014 +0100 @@ -2,6 +2,7 @@ import com.intellij.openapi.util.Pair; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*; +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.diff.ContentProcessor; import jetbrains.buildServer.util.graph.DAG; import jetbrains.buildServer.util.graph.DAGs; import jetbrains.buildServer.vcs.ModificationData; @@ -108,6 +109,10 @@ return DAGs.createFromEdges(edges); } + public void loadSubstates(@NotNull final ContentProcessor processor) throws VcsException { + new LoadSubstatesCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings).call(processor); + } + public Map<String, SubRepo> getSubrepositories(@NotNull ModificationData m) { if (hasSubrepoConfigChanges(m)) return getSubrepositories(m.getVersion());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMountPointsSupportTest.java Wed Jan 08 16:37:57 2014 +0100 @@ -0,0 +1,81 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial; + +import jetbrains.buildServer.vcs.CheckoutRules; +import jetbrains.buildServer.vcs.VcsRoot; +import jetbrains.buildServer.vcs.impl.VcsRootImpl; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; + +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.ServerPluginConfigBuilder.serverPluginConfig; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository; +import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot; + +/** + * Created 03.01.14 14:10 + * + * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) + */ +@RequiredHgVersion(min = "1.7.0") +@Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion") +public class MercurialMountPointsSupportTest extends BaseMercurialTestCase { + + private File myRemoteRepository; + private MercurialMountPointsSupport mySupport; + private MercurialVcsSupport myVcs; + private File myRemoteRepo1; + private File myRemoteRepo2; + private File myRemoteRepo3; + private VcsRootImpl myRoot; + + @BeforeMethod + public void setUp() throws Exception { + super.setUp(); + ServerPluginConfig config = serverPluginConfig() + .cachesDir(myTempFiles.createTempDir()) + .hgPath(Util.getHgPath()) + .build(); + + myRemoteRepository = myTempFiles.createTempDir(); + Util.copyRepository(new File("mercurial-tests/testData/rep2"), myRemoteRepository); + MercurialSupportBuilder hgBuilder = mercurialSupport().withConfig(config); + MercurialVcsSupport vcs = hgBuilder.build(); + myVcs = vcs; + mySupport = new MercurialMountPointsSupport(vcs, hgBuilder.getHgRootFactory()); + + + File remoteRepoParentDir = myTempFiles.createTempDir(); + myRemoteRepo1 = new File(remoteRepoParentDir, "r1"); + myRemoteRepo2 = new File(remoteRepoParentDir, "r2"); + myRemoteRepo3 = new File(remoteRepoParentDir, "r3"); + copyRepository(new File("mercurial-tests/testData/subrepos/r1"), myRemoteRepo1); + copyRepository(new File("mercurial-tests/testData/subrepos/r2"), myRemoteRepo2); + copyRepository(new File("mercurial-tests/testData/subrepos/r3"), myRemoteRepo3); + ServerPluginConfig myPluginConfig = new ServerPluginConfigBuilder() + .cachesDir(myTempFiles.createTempDir()) + .detectSubrepoChanges(true) + .build(); + myVcs = mercurialSupport().withConfig(myPluginConfig).build(); + myRoot = vcsRoot().withUrl(myRemoteRepo1.getAbsolutePath()).withSubrepoChanges(true).build(); + } + + @Test(enabled = false) + public void should_return_commits_for_every_revision_in_state_local(HgVersion _) throws Exception { + VcsRoot root = vcsRoot().withUrl("F:\\Work\\ReSharper\\Psi.Features").build(); + myVcs.syncRepository(root); + + final long start = System.currentTimeMillis(); + mySupport.collectMountPoints(root, CheckoutRules.DEFAULT, 42); + + final long actual = System.currentTimeMillis() - start; + System.out.println("All mount points were computed in " + actual + " ms"); + } + + public void should_return_commits_for_every_revision_in_state(HgVersion _) throws Exception { + myVcs.syncRepository(myRoot); + mySupport.collectMountPoints(myRoot, CheckoutRules.DEFAULT, 42); + } + +}