| /* |
| * Copyright 2000-2013 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 git4idea.log; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vcs.VcsException; |
| import com.intellij.openapi.vcs.VcsKey; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.vcs.log.*; |
| import com.intellij.vcs.log.impl.HashImpl; |
| import com.intellij.vcs.log.impl.VcsRefImpl; |
| import git4idea.GitLocalBranch; |
| import git4idea.GitRemoteBranch; |
| import git4idea.GitVcs; |
| import git4idea.commands.GitCommand; |
| import git4idea.commands.GitSimpleHandler; |
| import git4idea.history.GitHistoryUtils; |
| import git4idea.history.GitLogParser; |
| import git4idea.repo.GitRepository; |
| import git4idea.repo.GitRepositoryChangeListener; |
| import git4idea.repo.GitRepositoryManager; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.*; |
| |
| /** |
| * @author Kirill Likhodedov |
| */ |
| public class GitLogProvider implements VcsLogProvider { |
| |
| private static final Logger LOG = Logger.getInstance(GitLogProvider.class); |
| |
| @NotNull private final Project myProject; |
| @NotNull private final GitRepositoryManager myRepositoryManager; |
| @NotNull private final VcsLogRefManager myRefSorter; |
| |
| public GitLogProvider(@NotNull Project project, @NotNull GitRepositoryManager repositoryManager) { |
| myProject = project; |
| myRepositoryManager = repositoryManager; |
| myRefSorter = new GitRefManager(myRepositoryManager); |
| } |
| |
| @NotNull |
| @Override |
| public List<? extends VcsFullCommitDetails> readFirstBlock(@NotNull VirtualFile root, boolean ordered) throws VcsException { |
| String[] params = { "HEAD", "--branches", "--remotes", "--tags", "--encoding=UTF-8", "--full-history", "--sparse", |
| "--max-count=" + VcsLogProvider.COMMIT_BLOCK_SIZE}; |
| if (ordered) { |
| params = ArrayUtil.append(params, "--date-order"); |
| } |
| return GitHistoryUtils.history(myProject, root, params); |
| } |
| |
| @NotNull |
| @Override |
| public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root) throws VcsException { |
| return GitHistoryUtils.readAllHashes(myProject, root); |
| } |
| |
| @NotNull |
| @Override |
| public List<? extends VcsShortCommitDetails> readShortDetails(@NotNull VirtualFile root, @NotNull List<String> hashes) throws VcsException { |
| return GitHistoryUtils.readMiniDetails(myProject, root, hashes); |
| } |
| |
| @NotNull |
| @Override |
| public List<? extends VcsFullCommitDetails> readFullDetails(@NotNull VirtualFile root, @NotNull List<String> hashes) throws VcsException { |
| return GitHistoryUtils.commitsDetails(myProject, root, hashes); |
| } |
| |
| @NotNull |
| @Override |
| public Collection<VcsRef> readAllRefs(@NotNull VirtualFile root) throws VcsException { |
| myRepositoryManager.waitUntilInitialized(); |
| GitRepository repository = myRepositoryManager.getRepositoryForRoot(root); |
| if (repository == null) { |
| LOG.error("Repository not found for root " + root); |
| return Collections.emptyList(); |
| } |
| |
| repository.update(); |
| Collection<GitLocalBranch> localBranches = repository.getBranches().getLocalBranches(); |
| Collection<GitRemoteBranch> remoteBranches = repository.getBranches().getRemoteBranches(); |
| Collection<VcsRef> refs = new ArrayList<VcsRef>(localBranches.size() + remoteBranches.size()); |
| for (GitLocalBranch localBranch : localBranches) { |
| refs.add(new VcsRefImpl(HashImpl.build(localBranch.getHash()), localBranch.getName(), GitRefManager.LOCAL_BRANCH, root)); |
| } |
| for (GitRemoteBranch remoteBranch : remoteBranches) { |
| refs.add(new VcsRefImpl(HashImpl.build(remoteBranch.getHash()), remoteBranch.getNameForLocalOperations(), |
| GitRefManager.REMOTE_BRANCH, root)); |
| } |
| String currentRevision = repository.getCurrentRevision(); |
| if (currentRevision != null) { // null => fresh repository |
| refs.add(new VcsRefImpl(HashImpl.build(currentRevision), "HEAD", GitRefManager.HEAD, root)); |
| } |
| |
| refs.addAll(readTags(root)); |
| return refs; |
| } |
| |
| // TODO this is to be removed when tags will be supported by the GitRepositoryReader |
| private Collection<? extends VcsRef> readTags(@NotNull VirtualFile root) throws VcsException { |
| GitSimpleHandler tagHandler = new GitSimpleHandler(myProject, root, GitCommand.LOG); |
| tagHandler.addParameters("--tags", "--no-walk", "--format=%H%d" + GitLogParser.RECORD_START_GIT, "--decorate=full"); |
| String out = tagHandler.run(); |
| Collection<VcsRef> refs = new ArrayList<VcsRef>(); |
| for (String record : out.split(GitLogParser.RECORD_START)) { |
| if (!StringUtil.isEmptyOrSpaces(record)) { |
| refs.addAll(RefParser.parseCommitRefs(record.trim(), root)); |
| } |
| } |
| return refs; |
| } |
| |
| @NotNull |
| @Override |
| public VcsKey getSupportedVcs() { |
| return GitVcs.getKey(); |
| } |
| |
| @NotNull |
| @Override |
| public VcsLogRefManager getReferenceManager() { |
| return myRefSorter; |
| } |
| |
| @Override |
| public void subscribeToRootRefreshEvents(@NotNull final Collection<VirtualFile> roots, @NotNull final VcsLogRefresher refresher) { |
| myProject.getMessageBus().connect(myProject).subscribe(GitRepository.GIT_REPO_CHANGE, new GitRepositoryChangeListener() { |
| @Override |
| public void repositoryChanged(@NotNull GitRepository repository) { |
| VirtualFile root = repository.getRoot(); |
| if (roots.contains(root)) { |
| refresher.refresh(root); |
| } |
| } |
| }); |
| } |
| } |