diff --git a/plugins/git4idea/src/git4idea/repo/GitRepoInfo.java b/plugins/git4idea/src/git4idea/repo/GitRepoInfo.java new file mode 100644 index 000000000000..ea774663488d --- /dev/null +++ b/plugins/git4idea/src/git4idea/repo/GitRepoInfo.java @@ -0,0 +1,117 @@ +/* + * 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.repo; + +import com.intellij.dvcs.repo.Repository; +import git4idea.GitLocalBranch; +import git4idea.GitRemoteBranch; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * @author Kirill Likhodedov + */ +public class GitRepoInfo { + + @Nullable private final GitLocalBranch myCurrentBranch; + @Nullable private final String myCurrentRevision; + @NotNull private final Repository.State myState; + @NotNull private final Collection myRemotes; + @NotNull private final Collection myLocalBranches; + @NotNull private final Collection myRemoteBranches; + @NotNull private final Collection myBranchTrackInfos; + + public GitRepoInfo(@Nullable GitLocalBranch currentBranch, @Nullable String currentRevision, @NotNull Repository.State state, + @NotNull Collection remotes, @NotNull Collection localBranches, + @NotNull Collection remoteBranches, @NotNull Collection branchTrackInfos) { + myCurrentBranch = currentBranch; + myCurrentRevision = currentRevision; + myState = state; + myRemotes = remotes; + myLocalBranches = localBranches; + myRemoteBranches = remoteBranches; + myBranchTrackInfos = branchTrackInfos; + } + + @Nullable + public GitLocalBranch getCurrentBranch() { + return myCurrentBranch; + } + + @NotNull + public Collection getRemotes() { + return myRemotes; + } + + @NotNull + public Collection getLocalBranches() { + return myLocalBranches; + } + + @NotNull + public Collection getRemoteBranches() { + return myRemoteBranches; + } + + @NotNull + public Collection getBranchTrackInfos() { + return myBranchTrackInfos; + } + + @Nullable + public String getCurrentRevision() { + return myCurrentRevision; + } + + @NotNull + public Repository.State getState() { + return myState; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GitRepoInfo info = (GitRepoInfo)o; + + if (!myBranchTrackInfos.equals(info.myBranchTrackInfos)) return false; + if (myCurrentBranch != null ? !myCurrentBranch.equals(info.myCurrentBranch) : info.myCurrentBranch != null) return false; + if (!myLocalBranches.equals(info.myLocalBranches)) return false; + if (!myRemoteBranches.equals(info.myRemoteBranches)) return false; + if (!myRemotes.equals(info.myRemotes)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myCurrentBranch != null ? myCurrentBranch.hashCode() : 0; + result = 31 * result + myRemotes.hashCode(); + result = 31 * result + myLocalBranches.hashCode(); + result = 31 * result + myRemoteBranches.hashCode(); + result = 31 * result + myBranchTrackInfos.hashCode(); + return result; + } + + @Override + public String toString() { + return String.format("GitRepoInfo{current=%s, remotes=%s, localBranches=%s, remoteBranches=%s, trackInfos=%s}", + myCurrentBranch, myRemotes, myLocalBranches, myRemoteBranches, myBranchTrackInfos); + } +} diff --git a/plugins/git4idea/src/git4idea/repo/GitRepository.java b/plugins/git4idea/src/git4idea/repo/GitRepository.java index 9b7dfa077d47..7a44b27e9db3 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepository.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepository.java @@ -69,6 +69,9 @@ public interface GitRepository extends Repository { GitUntrackedFilesHolder getUntrackedFilesHolder(); + @NotNull + GitRepoInfo getInfo(); + /** * Returns the current branch of this Git repository. * If the repository is being rebased, then the current branch is the branch being rebased (which was current before the rebase diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java index ac92fc3f3720..45c9ebccc540 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java @@ -30,7 +30,6 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.Collection; -import java.util.Collections; /** * @author Kirill Likhodedov @@ -42,10 +41,7 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository, @NotNull private final VirtualFile myGitDir; @Nullable private final GitUntrackedFilesHolder myUntrackedFilesHolder; - @Nullable private volatile GitLocalBranch myCurrentBranch; - @NotNull private volatile GitBranchesCollection myBranches = GitBranchesCollection.EMPTY; - @NotNull private volatile Collection myRemotes = Collections.emptyList(); - @NotNull private volatile Collection myBranchTrackInfos; + @NotNull private volatile GitRepoInfo myInfo; /** * Get the GitRepository instance from the {@link GitRepositoryManager}. @@ -115,10 +111,28 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository, return myUntrackedFilesHolder; } + @Override + @NotNull + public GitRepoInfo getInfo() { + return myInfo; + } + @Override @Nullable public GitLocalBranch getCurrentBranch() { - return myCurrentBranch; + return myInfo.getCurrentBranch(); + } + + @Nullable + @Override + public String getCurrentRevision() { + return myInfo.getCurrentRevision(); + } + + @NotNull + @Override + public State getState() { + return myInfo.getState(); } /** @@ -127,19 +141,20 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository, @Override @NotNull public GitBranchesCollection getBranches() { - return new GitBranchesCollection(myBranches); + GitRepoInfo info = myInfo; + return new GitBranchesCollection(info.getLocalBranches(), info.getRemoteBranches()); } @Override @NotNull public Collection getRemotes() { - return myRemotes; + return myInfo.getRemotes(); } @Override @NotNull public Collection getBranchTrackInfos() { - return myBranchTrackInfos; + return myInfo.getBranchTrackInfos(); } @Override @@ -159,31 +174,58 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository, @Override public void update() { - File configFile = new File(VfsUtilCore.virtualToIoFile(myGitDir), "config"); - GitConfig config = GitConfig.read(myPlatformFacade, configFile); - myRemotes = config.parseRemotes(); - readRepository(myRemotes); - myBranchTrackInfos = config.parseTrackInfos(myBranches.getLocalBranches(), myBranches.getRemoteBranches()); - notifyListeners(); + myInfo = readRepoInfo(this, myPlatformFacade, myReader, myInfo); } - private void readRepository(@NotNull Collection remotes) { - myState = myReader.readState(); - myCurrentRevision = myReader.readCurrentRevision(); - myCurrentBranch = myReader.readCurrentBranch(); - myBranches = myReader.readBranches(remotes); + @NotNull + private static GitRepoInfo readRepoInfo(@NotNull GitRepository repository, @NotNull GitPlatformFacade platformFacade, + @NotNull GitRepositoryReader reader, @Nullable GitRepoInfo previousInfo) { + File configFile = new File(VfsUtilCore.virtualToIoFile(repository.getGitDir()), "config"); + GitConfig config = GitConfig.read(platformFacade, configFile); + Collection remotes = config.parseRemotes(); + TempState tempState = readRepository(reader, remotes); + Collection trackInfos = config.parseTrackInfos(tempState.myBranches.getLocalBranches(), + tempState.myBranches.getRemoteBranches()); + GitRepoInfo info = new GitRepoInfo(tempState.myCurrentBranch, tempState.myCurrentRevision, tempState.myState, + remotes, tempState.myBranches.getLocalBranches(), + tempState.myBranches.getRemoteBranches(), trackInfos); + notifyListeners(repository, previousInfo, info); + return info; } - protected void notifyListeners() { - if (!Disposer.isDisposed(getProject())) { - getProject().getMessageBus().syncPublisher(GIT_REPO_CHANGE).repositoryChanged(this); + private static TempState readRepository(GitRepositoryReader reader, @NotNull Collection remotes) { + return new TempState(reader.readState(), reader.readCurrentRevision(), reader.readCurrentBranch(), reader.readBranches(remotes)); + } + + private static void notifyListeners(@NotNull GitRepository repository, @Nullable GitRepoInfo previousInfo, @NotNull GitRepoInfo info) { + // previous info can be null before the first update + if (Disposer.isDisposed(repository.getProject())) { + return; + } + if (!info.equals(previousInfo)) { + repository.getProject().getMessageBus().syncPublisher(GIT_REPO_CHANGE).repositoryChanged(repository); } } @NotNull @Override public String toLogString() { - return String.format("GitRepository{myCurrentBranch=%s, myCurrentRevision='%s', myState=%s, myRootDir=%s}", - myCurrentBranch, myCurrentRevision, myState, getRoot()); + return String.format("GitRepository " + getRoot() + " : " + myInfo); } + + private static class TempState { + private final State myState; + private final String myCurrentRevision; + private final GitLocalBranch myCurrentBranch; + private final GitBranchesCollection myBranches; + + public TempState(@NotNull State state, @Nullable String currentRevision, @Nullable GitLocalBranch currentBranch, + @NotNull GitBranchesCollection branches) { + myState = state; + myCurrentRevision = currentRevision; + myCurrentBranch = currentBranch; + myBranches = branches; + } + } + }