From d5cd60e887e4361a2c68c92a32aaeca82bc29a63 Mon Sep 17 00:00:00 2001 From: Irina Chernushina Date: Thu, 10 Sep 2009 12:37:10 +0400 Subject: [PATCH] VCS: allow Git to report changed on server files comparing the whole tree. !! requires fetch now. to be continued. --- .../git4idea/src/git4idea/GitBranchesSearcher.java | 58 ++++++++++++++++++ plugins/git4idea/src/git4idea/GitVcs.java | 14 +++++ .../src/git4idea/changes/GitChangeUtils.java | 22 +++++++ .../changes/GitOutgoingChangesProvider.java | 24 ++------ .../git4idea/src/git4idea/commands/GitHandler.java | 7 +++ .../src/git4idea/diff/GitTreeDiffProvider.java | 68 ++++++++++++++++++++++ .../src/git4idea/merge/MergeChangeCollector.java | 8 ++- .../idea/svn/integrate/ResolveWorker.java | 7 ++- .../AbstractSvnUpdateIntegrateEnvironment.java | 7 +-- .../jetbrains/idea/svn/update/SvnStatusWorker.java | 14 +++-- .../idea/svn/update/UpdateEventHandler.java | 2 +- 11 files changed, 194 insertions(+), 37 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/GitBranchesSearcher.java create mode 100644 plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java diff --git a/plugins/git4idea/src/git4idea/GitBranchesSearcher.java b/plugins/git4idea/src/git4idea/GitBranchesSearcher.java new file mode 100644 index 0000000000..369f4c6fc2 --- /dev/null +++ b/plugins/git4idea/src/git4idea/GitBranchesSearcher.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2009 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; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; + +import java.util.HashSet; +import java.util.Set; + +public class GitBranchesSearcher { + private GitBranch myLocal; + private GitBranch myRemote; + + public GitBranchesSearcher(final Project project, final VirtualFile root, final boolean findRemote) throws VcsException { + final Set usedBranches = new HashSet(); + myLocal = GitBranch.current(project, root); + if (myLocal == null) return; + usedBranches.add(myLocal); + + GitBranch remote = myLocal; + while (true) { + remote = remote.tracked(project, root); + if (remote == null) return; + + if ((! findRemote) || remote.isRemote()) { + myRemote = remote; + return; + } + + if (usedBranches.contains(remote)) return; + usedBranches.add(remote); + } + } + + public GitBranch getLocal() { + return myLocal; + } + + public GitBranch getRemote() { + return myRemote; + } +} diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index 7f74c8ec88..f51cbfef32 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -49,6 +49,7 @@ import git4idea.config.GitVcsConfigurable; import git4idea.config.GitVcsSettings; import git4idea.config.GitVersion; import git4idea.diff.GitDiffProvider; +import git4idea.diff.GitTreeDiffProvider; import git4idea.history.GitHistoryProvider; import git4idea.i18n.GitBundle; import git4idea.merge.GitMergeProvider; @@ -166,6 +167,8 @@ public class GitVcs extends AbstractVcs { */ private GitConfigTracker myConfigTracker; + private final TreeDiffProvider myTreeDiffProvider; + public static GitVcs getInstance(@NotNull Project project) { return (GitVcs)ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME); } @@ -194,6 +197,7 @@ public class GitVcs extends AbstractVcs { myMergeProvider = new GitMergeProvider(myProject); myCommittedChangeListProvider = new GitCommittedChangeListProvider(myProject); myOutgoingChangesProvider = new GitOutgoingChangesProvider(myProject); + myTreeDiffProvider = new GitTreeDiffProvider(myProject); } /** @@ -629,4 +633,14 @@ public class GitVcs extends AbstractVcs { protected VcsOutgoingChangesProvider getOutgoingProviderImpl() { return myOutgoingChangesProvider; } + + @Override + public RemoteDifferenceStrategy getRemoteDifferenceStrategy() { + return RemoteDifferenceStrategy.ASK_TREE_PROVIDER; + } + + @Override + protected TreeDiffProvider getTreeDiffProviderImpl() { + return myTreeDiffProvider; + } } diff --git a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java index 2b3e763e82..ab35c2c97e 100644 --- a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java +++ b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java @@ -1,6 +1,7 @@ package git4idea.changes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; @@ -16,6 +17,7 @@ import git4idea.commands.GitSimpleHandler; import git4idea.commands.StringScanner; import org.jetbrains.annotations.NonNls; +import java.io.File; import java.util.*; /** @@ -59,6 +61,26 @@ public class GitChangeUtils { } } + public static Collection parseDiffForPaths(final String rootPath, final StringScanner s) throws VcsException { + final Collection result = new LinkedList(); + + while (s.hasMoreData()) { + if (s.isEol()) { + s.nextLine(); + continue; + } + if ("CADUMR".indexOf(s.peek()) == -1) { + // exit if there is no next character + break; + } + String[] tokens = s.line().split("\t"); + String path = tokens[tokens.length - 1]; + path = rootPath + File.separator + GitUtil.unescapePath(path); + path = FileUtil.toSystemDependentName(path); + result.add(path); + } + return result; + } /** * Parse changes from lines diff --git a/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java b/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java index 0cd5766942..426d2f98b3 100644 --- a/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java @@ -5,14 +5,12 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsOutgoingChangesProvider; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; -import git4idea.GitBranch; +import git4idea.GitBranchesSearcher; import git4idea.GitUtil; import git4idea.commands.GitSimpleHandler; import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Set; public class GitOutgoingChangesProvider implements VcsOutgoingChangesProvider { private final Project myProject; @@ -22,26 +20,12 @@ public class GitOutgoingChangesProvider implements VcsOutgoingChangesProvider { } public List getOutgoingChanges(final VirtualFile vcsRoot, final boolean findRemote) throws VcsException { - final Set usedBranches = new HashSet(); - final GitBranch currentBranch = GitBranch.current(myProject, vcsRoot); - if (currentBranch == null) return Collections.emptyList(); - usedBranches.add(currentBranch); + final GitBranchesSearcher searcher = new GitBranchesSearcher(myProject, vcsRoot, findRemote); + if (searcher.getLocal() == null || searcher.getRemote() == null) return Collections.emptyList(); - GitBranch remoteBranch = currentBranch; - while (true) { - remoteBranch = remoteBranch.tracked(myProject, vcsRoot); - if (remoteBranch == null) return Collections.emptyList(); - - if ((! findRemote) || remoteBranch.isRemote()) break; - - if (usedBranches.contains(remoteBranch)) return Collections.emptyList(); - usedBranches.add(remoteBranch); - } - - final GitBranch finalRemoteBranch = remoteBranch; return GitUtil.getLocalCommittedChanges(myProject, vcsRoot, new Consumer() { public void consume(final GitSimpleHandler handler) { - handler.addParameters(finalRemoteBranch.getFullName() + "..HEAD"); + handler.addParameters(searcher.getRemote().getFullName() + "..HEAD"); } }); } diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 2436d617a8..aea355d717 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -402,6 +402,13 @@ public abstract class GitHandler { } } + public void addRelativePathsForFiles(@NotNull final Collection files) { + checkNotStarted(); + for (File file : files) { + myCommandLine.addParameter(GitUtil.relativePath(myWorkingDirectory, file)); + } + } + /** * Add virtual file parameters. The parameters are made relative to the working directory * diff --git a/plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java b/plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java new file mode 100644 index 0000000000..dce4a1aef5 --- /dev/null +++ b/plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2009 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.diff; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.TreeDiffProvider; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; +import git4idea.GitBranchesSearcher; +import git4idea.changes.GitChangeUtils; +import git4idea.commands.GitHandler; +import git4idea.commands.GitSimpleHandler; +import git4idea.commands.StringScanner; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +public class GitTreeDiffProvider implements TreeDiffProvider { + private final static Logger LOG = Logger.getInstance("#git4idea.diff.GitTreeDiffProvider"); + private final Project myProject; + + public GitTreeDiffProvider(final Project project) { + myProject = project; + } + + public Collection getRemotelyChanged(final VirtualFile vcsRoot, final Collection paths) { + try { + final GitBranchesSearcher searcher = new GitBranchesSearcher(myProject, vcsRoot, true); + if (searcher.getLocal() == null || searcher.getRemote() == null) return Collections.emptyList(); + + GitSimpleHandler handler = new GitSimpleHandler(myProject, vcsRoot, GitHandler.DIFF); + handler.addParameters("--name-status", "--diff-filter=ADCMRUX", "-M", "HEAD..." + searcher.getRemote().getFullName()); + handler.setNoSSH(true); + handler.setSilent(true); + handler.setStdoutSuppressed(true); + handler.endOptions(); + final Collection files = new ArrayList(paths.size()); + for (String path : paths) { + files.add(new File(path)); + } + handler.addRelativePathsForFiles(files); + + String output = handler.run(); + return GitChangeUtils.parseDiffForPaths(vcsRoot.getPath(), new StringScanner(output)); + } + catch (VcsException e) { + LOG.info(e); + return Collections.emptyList(); + } + } +} diff --git a/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java b/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java index c16f45a489..e1dde0fdc7 100644 --- a/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java +++ b/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java @@ -18,11 +18,13 @@ package git4idea.merge; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.update.FileGroup; import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitRevisionNumber; import git4idea.GitUtil; +import git4idea.GitVcs; import git4idea.commands.GitHandler; import git4idea.commands.GitSimpleHandler; import git4idea.commands.StringScanner; @@ -80,6 +82,7 @@ public class MergeChangeCollector { * @param exceptions a list of exceptions */ public void collect(List exceptions) { + final VcsKey vcsKey = GitVcs.getKey(); try { // collect unmerged String root = myRoot.getPath(); @@ -98,7 +101,7 @@ public class MergeChangeCollector { continue; } String path = root + "/" + GitUtil.unescapePath(relative); - myUpdates.getGroupById(FileGroup.MERGED_WITH_CONFLICT_ID).add(path); + myUpdates.getGroupById(FileGroup.MERGED_WITH_CONFLICT_ID).add(path, vcsKey, null); } GitRevisionNumber currentHead = GitRevisionNumber.resolve(myProject, myRoot, "HEAD"); // collect other changes (ignoring unmerged) @@ -199,8 +202,9 @@ public class MergeChangeCollector { */ private void addAll(String id, TreeSet paths) { FileGroup fileGroup = myUpdates.getGroupById(id); + final VcsKey vcsKey = GitVcs.getKey(); for (String path : paths) { - fileGroup.add(path); + fileGroup.add(path, vcsKey, null); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java index dc6061d6fe..b522298a67 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java @@ -3,6 +3,7 @@ package org.jetbrains.idea.svn.integrate; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.AbstractVcsHelper; +import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vcs.update.FileGroup; import com.intellij.openapi.vcs.update.UpdateFilesHelper; @@ -10,8 +11,9 @@ import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnUtil; -import org.jetbrains.idea.svn.update.SvnUpdateGroups; +import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.actions.SvnMergeProvider; +import org.jetbrains.idea.svn.update.SvnUpdateGroups; import java.util.ArrayList; import java.util.List; @@ -84,11 +86,12 @@ public class ResolveWorker { final FileGroup mergedGroup = updatedFiles.getGroupById(FileGroup.MERGED_ID); final FileGroup conflictedGroup = updatedFiles.getGroupById(FileGroup.MERGED_WITH_CONFLICT_ID); + final VcsKey vcsKey = SvnVcs.getKey(); for (final VirtualFile mergedFile : mergedFiles) { String path = FileUtil.toSystemDependentName(mergedFile.getPresentableUrl()); conflictedGroup.remove(path); - mergedGroup.add(path); + mergedGroup.add(path, vcsKey, null); mergedFile.refresh(false, false); // for additionally created files removal to be detected diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java index 566a45a5bc..4f84e49d21 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java @@ -257,12 +257,7 @@ public abstract class AbstractSvnUpdateIntegrateEnvironment implements UpdateEnv final String path = FileUtil.toSystemDependentName(mergedFile.getPresentableUrl()); final VcsRevisionNumber revision = conflictedGroup.getRevision(myVcsManager, path); conflictedGroup.remove(path); - if (revision != null) { - mergedGroup.add(path, myVcs, revision); - } - else { - mergedGroup.add(path); - } + mergedGroup.add(path, myVcs.getKeyInstanceMethod(), revision); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnStatusWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnStatusWorker.java index 062377fa36..bc36bcf610 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnStatusWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnStatusWorker.java @@ -3,6 +3,7 @@ package org.jetbrains.idea.svn.update; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.update.FileGroup; import com.intellij.openapi.vcs.update.UpdatedFiles; import org.jetbrains.idea.svn.SvnBundle; @@ -43,6 +44,7 @@ public class SvnStatusWorker { if (progress != null) { progress.setText(SvnBundle.message("progress.text.update.computing.post.update.status", myRoot.getAbsolutePath())); } + final VcsKey vcsKey = SvnVcs.getKey(); statusClient.doStatus(myRoot, true, false, false, false, new ISVNStatusHandler() { public void handleStatus(SVNStatus status) { if (status.getFile() == null) { @@ -63,29 +65,29 @@ public class SvnStatusWorker { String path = status.getFile().getAbsolutePath(); if (status.getContentsStatus() == SVNStatusType.STATUS_ADDED) { - myPostUpdateFiles.getGroupById(FileGroup.LOCALLY_ADDED_ID).add(path); + myPostUpdateFiles.getGroupById(FileGroup.LOCALLY_ADDED_ID).add(path, vcsKey, null); } else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED) { // may conflict with update status. FileGroup group = myPostUpdateFiles.getGroupById(FileGroup.MERGED_WITH_CONFLICT_ID); if (group != null && (group.getFiles() == null || !group.getFiles().contains(path))) { - group.add(path); + group.add(path, vcsKey, null); } } else if (status.getContentsStatus() == SVNStatusType.STATUS_DELETED) { - myPostUpdateFiles.getGroupById(FileGroup.LOCALLY_REMOVED_ID).add(path); + myPostUpdateFiles.getGroupById(FileGroup.LOCALLY_REMOVED_ID).add(path, vcsKey, null); } else if (status.getContentsStatus() == SVNStatusType.STATUS_REPLACED) { - myPostUpdateFiles.getGroupById(FileGroup.LOCALLY_ADDED_ID).add(path); + myPostUpdateFiles.getGroupById(FileGroup.LOCALLY_ADDED_ID).add(path, vcsKey, null); } else if (status.getContentsStatus() == SVNStatusType.STATUS_MODIFIED || status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) { - myPostUpdateFiles.getGroupById(FileGroup.MODIFIED_ID).add(path); + myPostUpdateFiles.getGroupById(FileGroup.MODIFIED_ID).add(path, vcsKey, null); } else if (status.getContentsStatus() == SVNStatusType.STATUS_UNVERSIONED || status.getContentsStatus() == SVNStatusType.STATUS_OBSTRUCTED) { if (status.getFile().isFile() || !SVNWCUtil.isVersionedDirectory(status.getFile())) { - myPostUpdateFiles.getGroupById(FileGroup.UNKNOWN_ID).add(path); + myPostUpdateFiles.getGroupById(FileGroup.UNKNOWN_ID).add(path, vcsKey, null); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java index dc0799f217..1e8a5ea4b5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java @@ -183,7 +183,7 @@ public class UpdateEventHandler implements ISVNEventHandler { protected void addFileToGroup(final String id, final SVNEvent event) { final FileGroup fileGroup = myUpdatedFiles.getGroupById(id); final String path = event.getFile().getAbsolutePath(); - fileGroup.add(path); + fileGroup.add(path, SvnVcs.getKey(), null); if (event.getErrorMessage() != null) { fileGroup.addError(path, event.getErrorMessage().getMessage()); } -- 2.11.4.GIT