diff options
Diffstat (limited to 'platform/vcs-log/impl/src/com/intellij')
6 files changed, 157 insertions, 23 deletions
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java index 5a1766d9cb81..f0bf75c08dcf 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java @@ -48,11 +48,33 @@ public class VcsLogFilterer { @NotNull public AbstractVcsLogTableModel applyFiltersAndUpdateUi(@NotNull DataPack dataPack, @NotNull VcsLogFilterCollection filters) { resetFilters(dataPack); + VcsLogHashFilter hashFilter = filters.getHashFilter(); + if (hashFilter != null && !hashFilter.getHashes().isEmpty()) { // hashes should be shown, no matter if they match other filters or not + return applyHashFilter(dataPack, hashFilter.getHashes()); + } List<VcsLogDetailsFilter> detailsFilters = filters.getDetailsFilters(); applyGraphFilters(dataPack, filters.getBranchFilter()); return applyDetailsFilter(dataPack, detailsFilters); } + private GraphTableModel applyHashFilter(@NotNull DataPack dataPack, @NotNull Collection<String> hashes) { + final List<Integer> indices = ContainerUtil.mapNotNull(hashes, new Function<String, Integer>() { + @Override + public Integer fun(String partOfHash) { + Hash hash = myLogDataHolder.findHashByString(partOfHash); + return hash != null ? myLogDataHolder.getCommitIndex(hash) : null; + } + }); + dataPack.getGraphFacade().setVisibleBranches(null); + dataPack.getGraphFacade().setFilter(new Condition<Integer>() { + @Override + public boolean value(Integer integer) { + return indices.contains(integer); + } + }); + return new GraphTableModel(dataPack, myLogDataHolder, myUI, LoadMoreStage.ALL_REQUESTED); + } + private static void resetFilters(@NotNull DataPack dataPack) { GraphFacade facade = dataPack.getGraphFacade(); facade.setVisibleBranches(null); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java index 12996f91c116..c7ab5e324b3d 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java @@ -15,12 +15,14 @@ */ package com.intellij.vcs.log.data; +import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.progress.impl.ProgressManagerImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; @@ -272,22 +274,23 @@ public class VcsLogRefresherImpl implements VcsLogRefresher { Map<VirtualFile, Collection<VcsRef>> currentRefs = myCurrentDataPack.getRefsModel().getAllRefsByRoot(); try { if (permanentGraph != null) { - loadLogAndRefs(roots, currentRefs, myRecentCommitCount); - List<? extends GraphCommit<Integer>> compoundLog = compound(ContainerUtil.map(myLoadedInfos.values(), - new Function<LogAndRefs, List<? extends GraphCommit<Integer>>>() { - @Override - public List<? extends GraphCommit<Integer>> fun( - LogAndRefs refs) { - return refs.log; - } - })); - Map<VirtualFile, Collection<VcsRef>> allNewRefs = getAllNewRefs(myLoadedInfos, currentRefs); - List<GraphCommit<Integer>> joinedFullLog = join(compoundLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs); - if (joinedFullLog != null) { - return DataPack.build(joinedFullLog, new RefsModel(allNewRefs, myHashMap.asIndexGetter()), - myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, true); + int commitCount = myRecentCommitCount; + for (int attempt = 0; attempt <= 1; attempt++) { + loadLogAndRefs(roots, currentRefs, commitCount); + List<? extends GraphCommit<Integer>> compoundLog = compoundLoadedLogs(myLoadedInfos.values()); + Map<VirtualFile, Collection<VcsRef>> allNewRefs = getAllNewRefs(myLoadedInfos, currentRefs); + List<GraphCommit<Integer>> joinedFullLog = join(compoundLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs); + if (joinedFullLog == null) { + commitCount *= 5; + } + else { + return DataPack.build(joinedFullLog, new RefsModel(allNewRefs, myHashMap.asIndexGetter()), + myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, true); + } } - // couldn't join => need to reload everything; this shouldn't happen often, the error is logged in join(). + // couldn't join => need to reload everything; if 5000 commits is still not enough, it's worth reporting: + LOG.error("Couldn't join " + commitCount + " recent commits to the log (" + permanentGraph.getAllCommits().size() + " commits)", + new Attachment("recent_commits", toLogString(myLoadedInfos))); } Pair<PermanentGraph<Integer>, Map<VirtualFile, Collection<VcsRef>>> fullLogAndRefs = loadFullLog(); @@ -302,6 +305,38 @@ public class VcsLogRefresherImpl implements VcsLogRefresher { } } + private String toLogString(Map<VirtualFile, LogAndRefs> infos) { + StringBuilder sb = new StringBuilder(); + for (Map.Entry<VirtualFile, LogAndRefs> entry : infos.entrySet()) { + sb.append(entry.getKey().getName()); + sb.append(" LOG:\n"); + sb.append(StringUtil.join(entry.getValue().log, new Function<GraphCommit<Integer>, String>() { + @Override + public String fun(GraphCommit<Integer> commit) { + return commit.getId() + "<-" + StringUtil.join(commit.getParents(), ","); + } + }, "\n")); + sb.append("\nREFS:\n"); + sb.append(StringUtil.join(entry.getValue().refs, new Function<VcsRef, String>() { + @Override + public String fun(VcsRef ref) { + return ref.getName() + "(" + myHashMap.getCommitIndex(ref.getCommitHash()) + ")"; + } + }, ",")); + } + return sb.toString(); + } + + @NotNull + private List<? extends GraphCommit<Integer>> compoundLoadedLogs(@NotNull Collection<LogAndRefs> logsAndRefs) { + return compound(ContainerUtil.map(logsAndRefs, new Function<LogAndRefs, List<? extends GraphCommit<Integer>>>() { + @Override + public List<? extends GraphCommit<Integer>> fun(LogAndRefs refs) { + return refs.log; + } + })); + } + @NotNull private Map<VirtualFile, Collection<VcsRef>> getAllNewRefs(@NotNull Map<VirtualFile, LogAndRefs> newInfo, @NotNull Map<VirtualFile, Collection<VcsRef>> previousRefs) { @@ -374,7 +409,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher { return commits; } catch (VcsLogRefreshNotEnoughDataException e) { - LOG.error(e); // collecting information : how often this situation happens, do we need to try to load more or can safely reload all + LOG.info(e); } catch (IllegalStateException e) { LOG.error(e); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java index 285e3ce91079..3fbb7cb7b82f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java @@ -27,17 +27,20 @@ public class VcsLogFilterCollectionImpl implements VcsLogFilterCollection { @Nullable private final VcsLogBranchFilter myBranchFilter; @Nullable private final VcsLogUserFilter myUserFilter; + @Nullable private final VcsLogHashFilter myHashFilter; @Nullable private final VcsLogDateFilter myDateFilter; @Nullable private final VcsLogTextFilter myTextFilter; @Nullable private final VcsLogStructureFilter myStructureFilter; public VcsLogFilterCollectionImpl(@Nullable VcsLogBranchFilter branchFilter, @Nullable VcsLogUserFilter userFilter, + @Nullable VcsLogHashFilter hashFilter, @Nullable VcsLogDateFilter dateFilter, @Nullable VcsLogTextFilter textFilter, @Nullable VcsLogStructureFilter structureFilter) { myBranchFilter = branchFilter; myUserFilter = userFilter; + myHashFilter = hashFilter; myDateFilter = dateFilter; myTextFilter = textFilter; myStructureFilter = structureFilter; @@ -49,6 +52,12 @@ public class VcsLogFilterCollectionImpl implements VcsLogFilterCollection { return myBranchFilter; } + @Override + @Nullable + public VcsLogHashFilter getHashFilter() { + return myHashFilter; + } + @Nullable @Override public VcsLogUserFilter getUserFilter() { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogHashFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogHashFilterImpl.java new file mode 100644 index 000000000000..ff747f4f37d4 --- /dev/null +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogHashFilterImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2014 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 com.intellij.vcs.log.impl; + +import com.intellij.vcs.log.VcsLogHashFilter; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class VcsLogHashFilterImpl implements VcsLogHashFilter { + + @NotNull private final Collection<String> myHashes; + + public VcsLogHashFilterImpl(@NotNull Collection<String> hashes) { + myHashes = hashes; + } + + @NotNull + @Override + public Collection<String> getHashes() { + return myHashes; + } +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java index 88b2b449ac69..016f08451a95 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogSettingsImpl.java @@ -45,9 +45,4 @@ public class VcsLogSettingsImpl implements VcsLogSettings, PersistentStateCompon public void setShowBranchesPanel(boolean show) { myState.SHOW_BRANCHES_PANEL = show; } - - public void setRecentCommitsBlockSize(int commitCount) { - myState.RECENT_COMMITS_COUNT = commitCount; - } - } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java index d18c99c4e24c..9a44f320f040 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java @@ -20,15 +20,20 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.ex.CustomComponentAction; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.SearchTextField; import com.intellij.ui.SearchTextFieldWithStoredHistory; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl; +import com.intellij.vcs.log.impl.VcsLogHashFilterImpl; import com.intellij.vcs.log.ui.VcsLogUiImpl; import org.jetbrains.annotations.NotNull; @@ -43,6 +48,9 @@ import java.util.List; */ public class VcsLogClassicFilterUi implements VcsLogFilterUi { + private static final Logger LOG = Logger.getInstance(VcsLogClassicFilterUi.class); + private static final String HASH_PATTERN = "[a-fA-F0-9]{7,}"; + @NotNull private final SearchTextField myTextFilter; @NotNull private final VcsLogUiImpl myUi; @NotNull private final DefaultActionGroup myActionGroup; @@ -104,9 +112,38 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { @NotNull @Override public VcsLogFilterCollection getFilters() { - VcsLogTextFilter textFilter = !myTextFilter.getText().isEmpty() ? new VcsLogTextFilterImpl(myTextFilter.getText().trim()) : null; + Pair<VcsLogTextFilter, VcsLogHashFilter> filtersFromText = getFiltersFromTextArea(myTextFilter.getText().trim()); return new VcsLogFilterCollectionImpl(myBranchFilterComponent.getFilter(), myUserFilterComponent.getFilter(), - myDateFilterComponent.getFilter(), textFilter, myStructureFilterComponent.getFilter()); + filtersFromText.second, myDateFilterComponent.getFilter(), + filtersFromText.first, myStructureFilterComponent.getFilter()); + } + + @NotNull + private static Pair<VcsLogTextFilter, VcsLogHashFilter> getFiltersFromTextArea(@NotNull String text) { + if (text.isEmpty()) { + return Pair.empty(); + } + List<String> hashes = ContainerUtil.newArrayList(); + for (String word : StringUtil.split(text, " ")) { + if (!StringUtil.isEmptyOrSpaces(word) && word.matches(HASH_PATTERN)) { + hashes.add(word); + } + else { + break; + } + } + + VcsLogTextFilter textFilter; + VcsLogHashFilterImpl hashFilter; + if (!hashes.isEmpty()) { // text is ignored if there are hashes in the text + textFilter = null; + hashFilter = new VcsLogHashFilterImpl(hashes); + } + else { + textFilter = new VcsLogTextFilterImpl(text); + hashFilter = null; + } + return Pair.<VcsLogTextFilter, VcsLogHashFilter>create(textFilter, hashFilter); } @Override |