/* * * * Copyright 2013-2014 Urs Wolfer * * * * 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 com.urswolfer.intellij.plugin.gerrit.git; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.gerrit.extensions.common.FetchInfo; import com.google.gerrit.extensions.common.RevisionInfo; import com.intellij.openapi.project.Project; import com.urswolfer.intellij.plugin.gerrit.rest.GerritUtil; import com.urswolfer.intellij.plugin.gerrit.util.NotificationBuilder; import com.urswolfer.intellij.plugin.gerrit.util.NotificationService; import git4idea.repo.GitRepository; import java.util.List; import java.util.concurrent.Callable; /** * This class helps to simultaneously fetch multiple revisions from a git repository. * * @author Thomas Forrer */ public class RevisionFetcher { private final GerritUtil gerritUtil; private final GerritGitUtil gerritGitUtil; private final NotificationService notificationService; private final Project project; private final GitRepository gitRepository; private final List<RevisionInfo> revisionInfoList = Lists.newArrayList(); private final List<FetchCallback> fetchCallbacks = Lists.newArrayList(); public RevisionFetcher(GerritUtil gerritUtil, GerritGitUtil gerritGitUtil, NotificationService notificationService, Project project, GitRepository gitRepository) { this.gerritUtil = gerritUtil; this.gerritGitUtil = gerritGitUtil; this.notificationService = notificationService; this.project = project; this.gitRepository = gitRepository; } public RevisionFetcher addRevision(RevisionInfo revisionInfo) { revisionInfoList.add(revisionInfo); return this; } /** * Fetch the changes for the provided revisions. * @param callback the callback will be executed as soon as all revisions have been fetched successfully */ public void fetch(final Callable<Void> callback) { for (RevisionInfo revisionInfo : revisionInfoList) { FetchCallback fetchCallback = new FetchCallback(callback); fetchCallbacks.add(fetchCallback); fetchChange(revisionInfo, fetchCallback); } } private void fetchChange(RevisionInfo revisionInfo, FetchCallback fetchCallback) { FetchInfo fetchInfo = gerritUtil.getFirstFetchInfo(revisionInfo); if (fetchInfo == null) { notifyError(); } else { String ref = fetchInfo.ref; String url = fetchInfo.url; gerritGitUtil.fetchChange(project, gitRepository, url, ref, fetchCallback); } } private void notifyError() { NotificationBuilder notification = new NotificationBuilder( project, "Cannot fetch changes", "No fetch information provided. If you are using Gerrit 2.8 or later, " + "you need to install the plugin 'download-commands' in Gerrit." ); notificationService.notifyError(notification); } private final class FetchCallback implements Callable<Void> { private final Callable<Void> callback; private boolean returned = false; private FetchCallback(Callable<Void> callback) { this.callback = callback; } @Override public Void call() throws Exception { try { return null; } finally { returned = true; if (allFetchCallbacksReturned()) { callback.call(); } } } private synchronized boolean allFetchCallbacksReturned() { return Iterables.all(fetchCallbacks, new Predicate<FetchCallback>() { @Override public boolean apply(FetchCallback fetchCallback) { return fetchCallback.returned; } }); } } }