view mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommitsAndMountPointsCommand.java @ 732:31a1aca3305c

Update copyright
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Tue, 14 Jan 2014 12:45:10 +0100
parents 785ab04c78da
children 091667cc54d5
line wrap: on
line source
/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;

import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgFileUtil;
import jetbrains.buildServer.util.FileUtil;
import jetbrains.buildServer.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import static jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommitsAndMountPointsParser.parseCommits;
import static jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommitsAndMountPointsParser.parseFileLog;

/**
 * Created 03.01.14 14:53
 *
 * @author Eugene Petrenko (eugene.petrenko@jetbrains.com)
 */
public class CommitsAndMountPointsCommand extends VcsRootCommand {
  private static final Logger LOG = Logger.getInstance(CommitsAndMountPointsCommand.class.getName());

  public CommitsAndMountPointsCommand(@NotNull final CommandSettings commandSettings,
                                      @NotNull final String hgPath,
                                      @NotNull final File workingDir,
                                      @NotNull final AuthSettings authSettings) {
    super(commandSettings.addHgEnv("HGENCODING", "UTF-8"), hgPath, workingDir, authSettings);
  }

  @NotNull
  private File createTmpDir() throws VcsException {
    try {
      return HgFileUtil.createTempDir();
    } catch (IOException e) {
      throw new VcsException("Unable to create temporary directory", e);
    }
  }

  @NotNull
  private File extractCommandPy(@NotNull final File root) throws VcsException {
    try {
      final File py = new File(root, "load-substates-command.py");

      FileUtil.copyResource(getClass(), "/python/load-substates-command.py", py);

      if (py.length() < 100) throw new IOException("Failed to unpack command resource");
      return py;
    } catch (IOException e) {
      throw new VcsException("Failed to extract .py file: " + e.getMessage(), e);
    }
  }

  public void call(@NotNull final Callback consumer) throws VcsException {
    final File root = createTmpDir();

    try {
      final File py = extractCommandPy(root);

      callImpl(root, py, consumer);
    } finally {
      FileUtil.delete(root);
    }
  }
  
  public interface Callback {
    void processHGSubFile(@NotNull final String fileId, @NotNull final String file);
    void processHGSubStateFile(@NotNull final String fileId, @NotNull final String file);
    void onCommit(
            @NotNull String commitNum,
            @NotNull String commitId,
            @NotNull String[] parents,
            @NotNull String branch,
            @NotNull String[] tags,
            @NotNull String author,
            @NotNull String message,
            @NotNull final Date timestamp,
            @Nullable String hgsubNodeId,
            @Nullable String hgsubstateNodeId);
  }

  private void callImpl(@NotNull final File root,
                        @NotNull final File commandPy,
                        @NotNull final Callback consumer) throws VcsException {
    final MercurialCommandLine cli = createCommandLine();
    cli.addParameter("--debug");
    cli.addParameter("--config");
    cli.addParameter("extensions.logextcj=" + commandPy);
    cli.addParameter("load-substates");
    cli.addParameter(new File(root, "result").getPath());

    final CommandResult res = runCommand(cli);
    final String output = res.getStdout();

    if (!output.contains("##Completed##")) throw new VcsException("Command failed: " + output);

    try {
      parseFileLog(new File(root, "result.hgsub"), new CommitsAndMountPointsParser.ContentsConsumer() {
        public void onCommit(@NotNull final String fileNodeId, @NotNull final String content) {
          consumer.processHGSubFile(fileNodeId, content);
        }
      });
      parseFileLog(new File(root, "result.hgsubstate"), new CommitsAndMountPointsParser.ContentsConsumer() {
        public void onCommit(@NotNull final String fileNodeId, @NotNull final String content) {
          consumer.processHGSubStateFile(fileNodeId, content);
        }
      });

      parseCommits(new File(root, "result.commits"), new CommitsAndMountPointsParser.CommitsConsumer() {
        public void onCommit(@NotNull String commitNum,
                             @NotNull String commitId,
                             @NotNull String[] parents,
                             @NotNull String branch,
                             @NotNull String[] tags,
                             @NotNull String author,
                             @NotNull String message,
                             @NotNull Date timestamp,
                             @Nullable String hgsubNodeId,
                             @Nullable String hgsubstateNodeId) {
          consumer.onCommit(commitNum, commitId, parents, branch, tags, author, message, timestamp, hgsubNodeId, hgsubstateNodeId);
        }
      });
    } catch (IOException e) {
      throw new VcsException("Failed to parse response files for 'load-substates' command. " + e.getMessage(), e);
    }
  }



}