mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] Synchronize GitRepository data update, notify only when needed.
Encapsulate all repository data (current branch, remotes, branches, etc.) to GitRepoInfo; store the reference in a volatile field; just change the reference on update(). Otherwise the information could have been in an inconsistent state (e.g. current branch might have been deleted after it was included into myBranches). Check the state change before notification, not to notify after each update() even if nothing changed.
This commit is contained in:
@@ -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<GitRemote> myRemotes;
|
||||
@NotNull private final Collection<GitLocalBranch> myLocalBranches;
|
||||
@NotNull private final Collection<GitRemoteBranch> myRemoteBranches;
|
||||
@NotNull private final Collection<GitBranchTrackInfo> myBranchTrackInfos;
|
||||
|
||||
public GitRepoInfo(@Nullable GitLocalBranch currentBranch, @Nullable String currentRevision, @NotNull Repository.State state,
|
||||
@NotNull Collection<GitRemote> remotes, @NotNull Collection<GitLocalBranch> localBranches,
|
||||
@NotNull Collection<GitRemoteBranch> remoteBranches, @NotNull Collection<GitBranchTrackInfo> branchTrackInfos) {
|
||||
myCurrentBranch = currentBranch;
|
||||
myCurrentRevision = currentRevision;
|
||||
myState = state;
|
||||
myRemotes = remotes;
|
||||
myLocalBranches = localBranches;
|
||||
myRemoteBranches = remoteBranches;
|
||||
myBranchTrackInfos = branchTrackInfos;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GitLocalBranch getCurrentBranch() {
|
||||
return myCurrentBranch;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<GitRemote> getRemotes() {
|
||||
return myRemotes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<GitLocalBranch> getLocalBranches() {
|
||||
return myLocalBranches;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<GitRemoteBranch> getRemoteBranches() {
|
||||
return myRemoteBranches;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<GitBranchTrackInfo> 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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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<GitRemote> myRemotes = Collections.emptyList();
|
||||
@NotNull private volatile Collection<GitBranchTrackInfo> 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<GitRemote> getRemotes() {
|
||||
return myRemotes;
|
||||
return myInfo.getRemotes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<GitBranchTrackInfo> 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<GitRemote> 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<GitRemote> remotes = config.parseRemotes();
|
||||
TempState tempState = readRepository(reader, remotes);
|
||||
Collection<GitBranchTrackInfo> 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<GitRemote> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user