diff options
Diffstat (limited to 'plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java')
-rw-r--r-- | plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java new file mode 100644 index 000000000000..f019035a373f --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java @@ -0,0 +1,127 @@ +/* + * 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 org.zmlx.hg4idea.push; + +import com.intellij.dvcs.push.PushSpec; +import com.intellij.dvcs.push.Pusher; +import com.intellij.dvcs.push.VcsPushOptionValue; +import com.intellij.dvcs.repo.Repository; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.VcsNotifier; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.action.HgCommandResultNotifier; +import org.zmlx.hg4idea.command.HgPushCommand; +import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.execution.HgCommandResultHandler; +import org.zmlx.hg4idea.repo.HgRepository; + +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class HgPusher extends Pusher { + + private static final Logger LOG = Logger.getInstance(HgPusher.class); + private static final String ONE = "one"; + private static Pattern PUSH_COMMITS_PATTERN = Pattern.compile(".*(?:added|pushed) (\\d+|" + ONE + ") changeset.*"); + // hg push command has definite exit values for some cases: + // mercurial returns 0 if push was successful, 1 if nothing to push. see hg push --help + private static int PUSH_SUCCEEDED_EXIT_VALUE = 0; + private static int NOTHING_TO_PUSH_EXIT_VALUE = 1; + + @Override + public void push(@NotNull Map<Repository, PushSpec> pushSpecs, @Nullable VcsPushOptionValue vcsPushOptionValue, boolean force) { + for (Map.Entry<Repository, PushSpec> entry : pushSpecs.entrySet()) { + Repository repository = entry.getKey(); + HgRepository hgRepository = (HgRepository)repository; + PushSpec hgSpec = entry.getValue(); + HgTarget destination = (HgTarget)hgSpec.getTarget(); + if (destination == null) { + continue; + } + HgPushSource source = (HgPushSource)hgSpec.getSource(); + Project project = repository.getProject(); + final HgPushCommand pushCommand = new HgPushCommand(project, repository.getRoot(), destination.myTarget); + pushCommand.setIsNewBranch(true); // set always true, because it just allow mercurial to create a new one if needed + pushCommand.setForce(force); + String branchName = source.getBranch(); + if (branchName.equals(hgRepository.getCurrentBookmark())) { + if (vcsPushOptionValue == HgVcsPushOptionValue.Current) { + pushCommand.setBookmarkName(branchName); + } + else { + pushCommand.setRevision(branchName); + } + } + else { + pushCommand.setBranchName(branchName); + } + push(project, pushCommand); + } + } + + public static void push(@NotNull final Project project, @NotNull HgPushCommand command) { + final VirtualFile repo = command.getRepo(); + command.execute(new HgCommandResultHandler() { + @Override + public void process(@Nullable HgCommandResult result) { + if (result == null) { + return; + } + + if (result.getExitValue() == PUSH_SUCCEEDED_EXIT_VALUE) { + int commitsNum = getNumberOfPushedCommits(result); + String successTitle = "Pushed successfully"; + String successDescription = String.format("Pushed %d %s [%s]", commitsNum, StringUtil.pluralize("commit", commitsNum), + repo.getPresentableName()); + VcsNotifier.getInstance(project).notifySuccess(successTitle, successDescription); + } + else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) { + VcsNotifier.getInstance(project).notifySuccess("Nothing to push"); + } + else { + new HgCommandResultNotifier(project).notifyError(result, "Push failed", + "Failed to push to [" + repo.getPresentableName() + "]"); + } + } + }); + } + + private static int getNumberOfPushedCommits(@NotNull HgCommandResult result) { + int numberOfCommitsInAllSubrepos = 0; + final List<String> outputLines = result.getOutputLines(); + for (String outputLine : outputLines) { + outputLine = outputLine.trim(); + final Matcher matcher = PUSH_COMMITS_PATTERN.matcher(outputLine); + if (matcher.matches()) { + try { + String numberOfCommits = matcher.group(1); + numberOfCommitsInAllSubrepos += ONE.equals(numberOfCommits) ? 1 : Integer.parseInt(numberOfCommits); + } + catch (NumberFormatException e) { + LOG.error("getNumberOfPushedCommits ", e); + return -1; + } + } + } + return numberOfCommitsInAllSubrepos; + } +} |