| /* |
| * 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.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<HgRepository, HgPushSource, HgTarget> { |
| |
| 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 |
| static int PUSH_SUCCEEDED_EXIT_VALUE = 0; |
| static int NOTHING_TO_PUSH_EXIT_VALUE = 1; |
| |
| @Override |
| public void push(@NotNull Map<HgRepository, PushSpec<HgPushSource, HgTarget>> pushSpecs, |
| @Nullable VcsPushOptionValue vcsPushOptionValue, boolean force) { |
| for (Map.Entry<HgRepository, PushSpec<HgPushSource, HgTarget>> entry : pushSpecs.entrySet()) { |
| HgRepository repository = entry.getKey(); |
| PushSpec<HgPushSource, HgTarget> hgSpec = entry.getValue(); |
| HgTarget destination = hgSpec.getTarget(); |
| HgPushSource source = 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(repository.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() + "]"); |
| } |
| } |
| }); |
| } |
| |
| 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; |
| } |
| } |