mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
[vcs-log] introduce support for the "--no-merges" option
IDEA-92263 GitOrigin-RevId: 68333cfa5e1b286d22fe7d3089abf385bd25c2a9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b03be48ffb
commit
3abc949823
@@ -129,6 +129,7 @@ com.intellij.vcs.log.VcsLogFilterCollection
|
||||
- sf:BRANCH_FILTER:com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
- sf:DATE_FILTER:com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
- sf:HASH_FILTER:com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
- sf:PARENT_FILTER:com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
- sf:RANGE_FILTER:com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
- sf:REVISION_FILTER:com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
- sf:ROOT_FILTER:com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
@@ -177,6 +178,11 @@ com.intellij.vcs.log.VcsLogObjectsFactory
|
||||
- a:createShortDetails(com.intellij.vcs.log.Hash,java.util.List,J,com.intellij.openapi.vfs.VirtualFile,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,J):com.intellij.vcs.log.VcsShortCommitDetails
|
||||
- a:createTimedCommit(com.intellij.vcs.log.Hash,java.util.List,J):com.intellij.vcs.log.TimedVcsCommit
|
||||
- a:createUser(java.lang.String,java.lang.String):com.intellij.vcs.log.VcsUser
|
||||
com.intellij.vcs.log.VcsLogParentFilter
|
||||
- com.intellij.vcs.log.VcsLogFilter
|
||||
- getKey():com.intellij.vcs.log.VcsLogFilterCollection$FilterKey
|
||||
- a:getMaxParents():I
|
||||
- a:getMinParents():I
|
||||
f:com.intellij.vcs.log.VcsLogProperties
|
||||
- sf:CASE_INSENSITIVE_REGEX:com.intellij.vcs.log.VcsLogProperties$VcsLogProperty
|
||||
- sf:HAS_COMMITTER:com.intellij.vcs.log.VcsLogProperties$VcsLogProperty
|
||||
@@ -184,6 +190,7 @@ f:com.intellij.vcs.log.VcsLogProperties
|
||||
- sf:SUPPORTS_INCREMENTAL_REFRESH:com.intellij.vcs.log.VcsLogProperties$VcsLogProperty
|
||||
- sf:SUPPORTS_INDEXING:com.intellij.vcs.log.VcsLogProperties$VcsLogProperty
|
||||
- sf:SUPPORTS_LOG_DIRECTORY_HISTORY:com.intellij.vcs.log.VcsLogProperties$VcsLogProperty
|
||||
- sf:SUPPORTS_PARENTS_FILTER:com.intellij.vcs.log.VcsLogProperties$VcsLogProperty
|
||||
- <init>():V
|
||||
f:com.intellij.vcs.log.VcsLogProperties$VcsLogProperty
|
||||
- getOrDefault(com.intellij.vcs.log.VcsLogProvider):java.lang.Object
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -25,10 +25,12 @@ public interface VcsLogFilterCollection {
|
||||
FilterKey<VcsLogTextFilter> TEXT_FILTER = FilterKey.create("text");
|
||||
FilterKey<VcsLogStructureFilter> STRUCTURE_FILTER = FilterKey.create("structure");
|
||||
FilterKey<VcsLogRootFilter> ROOT_FILTER = FilterKey.create("roots");
|
||||
FilterKey<VcsLogParentFilter> PARENT_FILTER = FilterKey.create("parent");
|
||||
|
||||
Collection<FilterKey<? extends VcsLogFilter>> STANDARD_KEYS = List.of(BRANCH_FILTER, REVISION_FILTER, RANGE_FILTER,
|
||||
USER_FILTER, HASH_FILTER, DATE_FILTER,
|
||||
TEXT_FILTER, STRUCTURE_FILTER, ROOT_FILTER);
|
||||
TEXT_FILTER, STRUCTURE_FILTER, ROOT_FILTER,
|
||||
PARENT_FILTER);
|
||||
|
||||
@Nullable <T extends VcsLogFilter> T get(@NotNull FilterKey<T> key);
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log
|
||||
|
||||
interface VcsLogParentFilter : VcsLogFilter {
|
||||
|
||||
val minParents: Int
|
||||
val maxParents: Int
|
||||
|
||||
override fun getKey(): VcsLogFilterCollection.FilterKey<*> = VcsLogFilterCollection.PARENT_FILTER
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -30,4 +30,8 @@ public final class VcsLogProperties {
|
||||
* True if VCS allows incrementally refresh commits in the log. False if full refresh should be performed.
|
||||
*/
|
||||
@NotNull public static final VcsLogProperty<Boolean> SUPPORTS_INCREMENTAL_REFRESH = new VcsLogProperty<>(true);
|
||||
/**
|
||||
* True if ths {@link VcsLogProvider} implementation supports filtering commits by parents count.
|
||||
*/
|
||||
@NotNull public static final VcsLogProperty<Boolean> SUPPORTS_PARENTS_FILTER = new VcsLogProperty<>(true);
|
||||
}
|
||||
|
||||
@@ -1320,7 +1320,6 @@ f:com.intellij.vcs.log.ui.VcsLogActionIds
|
||||
- sf:CHANGES_BROWSER_TOOLBAR_ACTION_GROUP:java.lang.String
|
||||
- sf:FILE_HISTORY_TOOLBAR_ACTION_GROUP:java.lang.String
|
||||
- sf:FILE_HISTORY_TOOLBAR_RIGHT_CORNER_ACTION_GROUP:java.lang.String
|
||||
- sf:GRAPH_OPTIONS_GROUP:java.lang.String
|
||||
- sf:HISTORY_POPUP_ACTION_GROUP:java.lang.String
|
||||
- sf:POPUP_ACTION_GROUP:java.lang.String
|
||||
- sf:TEXT_FILTER_SETTINGS_ACTION_GROUP:java.lang.String
|
||||
@@ -1702,13 +1701,6 @@ c:com.intellij.vcs.log.ui.actions.VcsLogCreatePatchActionProvider$Clipboard
|
||||
c:com.intellij.vcs.log.ui.actions.VcsLogCreatePatchActionProvider$Dialog
|
||||
- com.intellij.vcs.log.ui.actions.VcsLogCreatePatchActionProvider
|
||||
- <init>():V
|
||||
c:com.intellij.vcs.log.ui.actions.VcsLogGraphOptionsChooserGroup
|
||||
- com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
- com.intellij.openapi.project.DumbAware
|
||||
- <init>():V
|
||||
- getActionUpdateThread():com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
- getChildren(com.intellij.openapi.actionSystem.AnActionEvent):com.intellij.openapi.actionSystem.AnAction[]
|
||||
- update(com.intellij.openapi.actionSystem.AnActionEvent):V
|
||||
c:com.intellij.vcs.log.ui.actions.VcsLogToolbarPopupActionGroup
|
||||
- com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
- com.intellij.openapi.project.DumbAware
|
||||
@@ -1946,7 +1938,6 @@ f:com.intellij.vcs.log.ui.filter.BranchFilterModel
|
||||
- f:getRangeFilter():com.intellij.vcs.log.VcsLogRangeFilter
|
||||
- f:getRevisionFilter():com.intellij.vcs.log.VcsLogRevisionFilter
|
||||
- f:getVisibleRoots():java.util.Collection
|
||||
- f:onStructureFilterChanged(com.intellij.vcs.log.VcsLogRootFilter,com.intellij.vcs.log.VcsLogStructureFilter):V
|
||||
- f:setBranchFilter(com.intellij.vcs.log.VcsLogBranchFilter):V
|
||||
- f:setRangeFilter(com.intellij.vcs.log.VcsLogRangeFilter):V
|
||||
- f:setRevisionFilter(com.intellij.vcs.log.VcsLogRevisionFilter):V
|
||||
@@ -2047,6 +2038,19 @@ a:com.intellij.vcs.log.ui.filter.FilterModel$SingleFilterModel
|
||||
- pa:getFilterValues(com.intellij.vcs.log.VcsLogFilter):java.util.List
|
||||
- p:saveFilterToProperties(com.intellij.vcs.log.VcsLogFilter):V
|
||||
- setFilter(com.intellij.vcs.log.VcsLogFilter):V
|
||||
f:com.intellij.vcs.log.ui.filter.NoMergesFilterAction
|
||||
- com.intellij.openapi.project.DumbAwareToggleAction
|
||||
- <init>(com.intellij.vcs.log.ui.filter.ParentFilterModel):V
|
||||
- getActionUpdateThread():com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
- isSelected(com.intellij.openapi.actionSystem.AnActionEvent):Z
|
||||
- setSelected(com.intellij.openapi.actionSystem.AnActionEvent,Z):V
|
||||
- update(com.intellij.openapi.actionSystem.AnActionEvent):V
|
||||
f:com.intellij.vcs.log.ui.filter.ParentFilterModel
|
||||
- com.intellij.vcs.log.ui.filter.FilterModel$SingleFilterModel
|
||||
- <init>(com.intellij.vcs.log.impl.MainVcsLogUiProperties,java.util.Map,kotlin.jvm.functions.Function0,com.intellij.vcs.log.VcsLogFilterCollection):V
|
||||
- b:<init>(com.intellij.vcs.log.impl.MainVcsLogUiProperties,java.util.Map,kotlin.jvm.functions.Function0,com.intellij.vcs.log.VcsLogFilterCollection,I,kotlin.jvm.internal.DefaultConstructorMarker):V
|
||||
- f:isEnabled():Z
|
||||
- f:isVisible():Z
|
||||
c:com.intellij.vcs.log.ui.filter.StructureFilterPopupComponent
|
||||
- com.intellij.util.ui.FilterComponent
|
||||
- psf:ALL_ACTION_TEXT:java.util.function.Supplier
|
||||
@@ -2121,6 +2125,7 @@ c:com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi
|
||||
- pf:getBranchFilterModel():com.intellij.vcs.log.ui.filter.BranchFilterModel
|
||||
- pf:getDateFilterModel():com.intellij.vcs.log.ui.filter.DateFilterModel
|
||||
- getFilters():com.intellij.vcs.log.VcsLogFilterCollection
|
||||
- pf:getParentFilterModel():com.intellij.vcs.log.ui.filter.ParentFilterModel
|
||||
- pf:getStructureFilterModel():com.intellij.vcs.log.ui.filter.FileFilterModel
|
||||
- getTextFilterComponent():com.intellij.vcs.log.ui.filter.VcsLogTextFilterField
|
||||
- pf:getTextFilterModel():com.intellij.vcs.log.ui.filter.TextFilterModel
|
||||
@@ -2144,6 +2149,13 @@ pf:com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi$MainUiActionComponent
|
||||
*:com.intellij.vcs.log.ui.filter.VcsLogFilterUiEx$VcsLogFilterListener
|
||||
- java.util.EventListener
|
||||
- a:onFiltersChanged():V
|
||||
c:com.intellij.vcs.log.ui.filter.VcsLogGraphOptionsChooserGroup
|
||||
- com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
- com.intellij.openapi.project.DumbAware
|
||||
- <init>(com.intellij.vcs.log.ui.filter.ParentFilterModel):V
|
||||
- getActionUpdateThread():com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
- getChildren(com.intellij.openapi.actionSystem.AnActionEvent):com.intellij.openapi.actionSystem.AnAction[]
|
||||
- update(com.intellij.openapi.actionSystem.AnActionEvent):V
|
||||
a:com.intellij.vcs.log.ui.filter.VcsLogPopupComponentAction
|
||||
- com.intellij.openapi.project.DumbAwareAction
|
||||
- com.intellij.openapi.actionSystem.ex.CustomComponentAction
|
||||
@@ -2864,6 +2876,8 @@ f:com.intellij.vcs.log.visible.filters.VcsLogFilterObject
|
||||
- sf:fromDates(java.util.Date,java.util.Date):com.intellij.vcs.log.VcsLogDateFilter
|
||||
- sf:fromHash(java.lang.String):com.intellij.vcs.log.VcsLogHashFilter
|
||||
- sf:fromHashes(java.util.Collection):com.intellij.vcs.log.VcsLogHashFilter
|
||||
- sf:fromParentCount(java.lang.Integer,java.lang.Integer):com.intellij.vcs.log.VcsLogParentFilter
|
||||
- bs:fromParentCount$default(java.lang.Integer,java.lang.Integer,I,java.lang.Object):com.intellij.vcs.log.VcsLogParentFilter
|
||||
- sf:fromPaths(java.util.Collection):com.intellij.vcs.log.VcsLogStructureFilter
|
||||
- sf:fromPattern(java.lang.String,Z,Z):com.intellij.vcs.log.VcsLogTextFilter
|
||||
- bs:fromPattern$default(java.lang.String,Z,Z,I,java.lang.Object):com.intellij.vcs.log.VcsLogTextFilter
|
||||
@@ -2878,6 +2892,7 @@ f:com.intellij.vcs.log.visible.filters.VcsLogFilterObject
|
||||
- sf:fromUserNames(java.util.Collection,com.intellij.vcs.log.data.VcsLogData):com.intellij.vcs.log.VcsLogUserFilter
|
||||
- sf:fromUserNames(java.util.Collection,java.util.Map,java.util.Set):com.intellij.vcs.log.VcsLogUserFilter
|
||||
- sf:fromVirtualFiles(java.util.Collection):com.intellij.vcs.log.VcsLogStructureFilter
|
||||
- sf:noMerges():com.intellij.vcs.log.VcsLogParentFilter
|
||||
f:com.intellij.vcs.log.visible.filters.VcsLogFiltersKt
|
||||
- sf:getKeysToSet(com.intellij.vcs.log.VcsLogFilterCollection):java.util.Set
|
||||
- sf:getPresentation(com.intellij.vcs.log.VcsLogFilterCollection):java.lang.String
|
||||
@@ -2887,6 +2902,11 @@ f:com.intellij.vcs.log.visible.filters.VcsLogFiltersKt
|
||||
- sf:without(com.intellij.vcs.log.VcsLogFilterCollection,com.intellij.vcs.log.VcsLogFilterCollection$FilterKey):com.intellij.vcs.log.VcsLogFilterCollection
|
||||
- sf:without(com.intellij.vcs.log.VcsLogFilterCollection,java.lang.Class):com.intellij.vcs.log.VcsLogFilterCollection
|
||||
- sf:without(com.intellij.vcs.log.VcsLogFilterCollection,kotlin.jvm.functions.Function1):com.intellij.vcs.log.VcsLogFilterCollection
|
||||
f:com.intellij.vcs.log.visible.filters.VcsLogParentFilterImplKt
|
||||
- sf:getHasLowerBound(com.intellij.vcs.log.VcsLogParentFilter):Z
|
||||
- sf:getHasUpperBound(com.intellij.vcs.log.VcsLogParentFilter):Z
|
||||
- sf:getMatchesAll(com.intellij.vcs.log.VcsLogParentFilter):Z
|
||||
- sf:isNoMerges(com.intellij.vcs.log.VcsLogParentFilter):Z
|
||||
*:com.intellij.vcs.log.visible.filters.VcsLogTextFilterWithMatches
|
||||
- com.intellij.vcs.log.VcsLogTextFilter
|
||||
- matches(java.lang.String):Z
|
||||
|
||||
@@ -169,9 +169,6 @@
|
||||
</action>
|
||||
</group>
|
||||
|
||||
<group id="Vcs.Log.GraphOptionsGroup" class="com.intellij.vcs.log.ui.actions.VcsLogGraphOptionsChooserGroup" popup="true"
|
||||
icon="com.intellij.vcs.log.impl.VcsLogIcons.IntelliSort"/>
|
||||
|
||||
<group id="Vcs.Log.BranchActionsGroup" popup="false">
|
||||
<separator key="action.vcs.log.branches.separator"/>
|
||||
<reference id="Vcs.Log.CollapseAll"/>
|
||||
|
||||
@@ -231,6 +231,7 @@ vcs.log.filter.popup.advertisement.text.or.suffix=or {0}
|
||||
vcs.log.filter.popup.advertisement.with.key.text=Select one or more values separated with {0}, use {1} to finish
|
||||
vcs.log.filter.select.folders=Select in Tree\u2026
|
||||
vcs.log.filter.edit.folders=Select\u2026
|
||||
vcs.log.filter.no.merges=No Merges
|
||||
vcs.log.text.filter.action.text=Filter by Text or Hash
|
||||
vcs.log.branch.filter.action.text=Filter by Branch
|
||||
vcs.log.user.filter.action.text=Filter by User
|
||||
|
||||
@@ -36,7 +36,7 @@ import static com.intellij.vcs.log.ui.table.column.VcsLogColumnUtilKt.getColumns
|
||||
import static com.intellij.vcs.log.ui.table.column.VcsLogDefaultColumnKt.getDefaultDynamicColumns;
|
||||
|
||||
public @NonNls class VcsLogFeaturesCollector extends ProjectUsagesCollector {
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("vcs.log.ui", 4);
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("vcs.log.ui", 5);
|
||||
private static final EventId UI_INITIALIZED = GROUP.registerEvent("uiInitialized");
|
||||
private static final VarargEventId DETAILS = GROUP.registerVarargEvent("details", EventFields.Enabled);
|
||||
private static final VarargEventId DIFF_PREVIEW = GROUP.registerVarargEvent("diffPreview", EventFields.Enabled);
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.intellij.vcs.log.visible.CommitCountStage
|
||||
import com.intellij.vcs.log.visible.FilterKind
|
||||
|
||||
object VcsLogPerformanceStatisticsCollector : CounterUsagesCollector() {
|
||||
private val GROUP = EventLogGroup("vcs.log.performance", 5)
|
||||
private val GROUP = EventLogGroup("vcs.log.performance", 6)
|
||||
|
||||
val FILE_HISTORY_COMPUTING = GROUP.registerEvent("file.history.computed",
|
||||
VcsLogRepoSizeCollector.VCS_FIELD,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log.statistics;
|
||||
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup;
|
||||
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class VcsLogUsageTriggerCollector extends CounterUsagesCollector {
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("vcs.log.trigger", 7);
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("vcs.log.trigger", 8);
|
||||
private static final StringEventField CONTEXT = EventFields.String("context", List.of("history", "log"));
|
||||
private static final ClassEventField CLASS = EventFields.Class("class");
|
||||
public static final BooleanEventField PARENT_COMMIT = EventFields.Boolean("parent_commit");
|
||||
|
||||
@@ -9,7 +9,6 @@ public final @NonNls class VcsLogActionIds {
|
||||
public static final String TOOLBAR_ACTION_GROUP = "Vcs.Log.Toolbar.Internal";
|
||||
public static final String TOOLBAR_RIGHT_CORNER_ACTION_GROUP = "Vcs.Log.Toolbar.RightCorner";
|
||||
public static final String TEXT_FILTER_SETTINGS_ACTION_GROUP = "Vcs.Log.TextFilterSettings";
|
||||
public static final String GRAPH_OPTIONS_GROUP = "Vcs.Log.GraphOptionsGroup";
|
||||
public static final String BRANCH_ACTIONS_GROUP = "Vcs.Log.BranchActionsGroup";
|
||||
public static final String FILE_HISTORY_TOOLBAR_ACTION_GROUP = "Vcs.FileHistory.Toolbar";
|
||||
public static final String FILE_HISTORY_TOOLBAR_RIGHT_CORNER_ACTION_GROUP = "Vcs.FileHistory.Toolbar.RightCorner";
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log.ui.filter
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.project.DumbAwareToggleAction
|
||||
import com.intellij.vcs.log.VcsLogBundle
|
||||
import com.intellij.vcs.log.visible.filters.VcsLogFilterObject
|
||||
|
||||
class NoMergesFilterAction(private val parentFilterModel: ParentFilterModel) : DumbAwareToggleAction(VcsLogBundle.message("vcs.log.filter.no.merges")) {
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
return parentFilterModel.getFilter() != null
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabled = parentFilterModel.isEnabled
|
||||
e.presentation.isVisible = parentFilterModel.isVisible
|
||||
super.update(e)
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
if (state) {
|
||||
parentFilterModel.setFilter(VcsLogFilterObject.noMerges())
|
||||
}
|
||||
else {
|
||||
parentFilterModel.setFilter(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log.ui.filter
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.vcs.log.VcsLogFilterCollection
|
||||
import com.intellij.vcs.log.VcsLogParentFilter
|
||||
import com.intellij.vcs.log.VcsLogProperties
|
||||
import com.intellij.vcs.log.VcsLogProvider
|
||||
import com.intellij.vcs.log.impl.MainVcsLogUiProperties
|
||||
import com.intellij.vcs.log.visible.filters.VcsLogFilterObject
|
||||
|
||||
class ParentFilterModel(uiProperties: MainVcsLogUiProperties,
|
||||
private val logProviders: Map<VirtualFile, VcsLogProvider>,
|
||||
private val visibleRootsProvider: () -> Collection<VirtualFile>? = { null }, filters: VcsLogFilterCollection?) :
|
||||
FilterModel.SingleFilterModel<VcsLogParentFilter>(VcsLogFilterCollection.PARENT_FILTER, uiProperties, filters) {
|
||||
|
||||
private fun createParentFilter(values: List<String>): VcsLogParentFilter? {
|
||||
if (values.size != 2) return null
|
||||
return VcsLogFilterObject.fromParentCount(values[0].toIntOrNull(), values[1].toIntOrNull())
|
||||
}
|
||||
|
||||
override fun createFilter(values: List<String>): VcsLogParentFilter? {
|
||||
return createParentFilter(values)
|
||||
}
|
||||
|
||||
override fun getFilterValues(filter: VcsLogParentFilter): List<String> {
|
||||
return listOf(filter.minParents.toString(), filter.maxParents.toString())
|
||||
}
|
||||
|
||||
val isVisible: Boolean
|
||||
get() = isSupported(logProviders.keys)
|
||||
|
||||
val isEnabled: Boolean
|
||||
get() = isSupported(visibleRootsProvider() ?: logProviders.keys)
|
||||
|
||||
private fun isSupported(roots: Collection<VirtualFile>) =
|
||||
roots.any { VcsLogProperties.SUPPORTS_PARENTS_FILTER.getOrDefault(logProviders[it]) }
|
||||
}
|
||||
@@ -54,6 +54,7 @@ open class VcsLogClassicFilterUi(private val logData: VcsLogData,
|
||||
protected val dateFilterModel: DateFilterModel
|
||||
protected val structureFilterModel: FileFilterModel
|
||||
protected val textFilterModel: TextFilterModel
|
||||
protected val parentFilterModel: ParentFilterModel
|
||||
|
||||
private val textFilterField: VcsLogTextFilterField
|
||||
|
||||
@@ -65,12 +66,13 @@ open class VcsLogClassicFilterUi(private val logData: VcsLogData,
|
||||
dateFilterModel = DateFilterModel(uiProperties, filters)
|
||||
structureFilterModel = FileFilterModel(logData.logProviders.keys, uiProperties, filters)
|
||||
textFilterModel = TextFilterModel(uiProperties, filters, parentDisposable)
|
||||
parentFilterModel = ParentFilterModel(uiProperties, logData.logProviders, ::visibleRoots, filters)
|
||||
|
||||
val field = TextFilterField(textFilterModel, parentDisposable)
|
||||
val toolbar = createTextActionsToolbar(field.textEditor)
|
||||
textFilterField = MyVcsLogTextFilterField(SearchFieldWithExtension(toolbar.component, field))
|
||||
|
||||
val models = arrayOf(branchFilterModel, userFilterModel, dateFilterModel, structureFilterModel, textFilterModel)
|
||||
val models = arrayOf(branchFilterModel, userFilterModel, dateFilterModel, structureFilterModel, textFilterModel, parentFilterModel)
|
||||
for (model in models) {
|
||||
model.addSetFilterListener {
|
||||
filterConsumer.accept(getFilters())
|
||||
@@ -140,6 +142,7 @@ open class VcsLogClassicFilterUi(private val logData: VcsLogData,
|
||||
addAll(structureFilterModel.filtersList)
|
||||
add(dateFilterModel.getFilter())
|
||||
add(userFilterModel.getFilter())
|
||||
add(parentFilterModel.getFilter())
|
||||
}.filterNotNull()
|
||||
return VcsLogFilterObject.collection(*filters.toTypedArray())
|
||||
}
|
||||
@@ -151,6 +154,7 @@ open class VcsLogClassicFilterUi(private val logData: VcsLogData,
|
||||
textFilterModel.setFilter(collection)
|
||||
dateFilterModel.setFilter(collection.get(VcsLogFilterCollection.DATE_FILTER))
|
||||
userFilterModel.setFilter(collection.get(VcsLogFilterCollection.USER_FILTER))
|
||||
parentFilterModel.setFilter(collection.get(VcsLogFilterCollection.PARENT_FILTER))
|
||||
}
|
||||
|
||||
protected open fun createBranchComponent(): AnAction? {
|
||||
@@ -178,7 +182,7 @@ open class VcsLogClassicFilterUi(private val logData: VcsLogData,
|
||||
}
|
||||
|
||||
protected fun createGraphComponent(): AnAction? {
|
||||
return ActionManager.getInstance().getAction(VcsLogActionIds.GRAPH_OPTIONS_GROUP)
|
||||
return VcsLogGraphOptionsChooserGroup(parentFilterModel)
|
||||
}
|
||||
|
||||
override fun addFilterListener(listener: VcsLogFilterListener) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log.ui.actions;
|
||||
package com.intellij.vcs.log.ui.filter;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
@@ -8,14 +8,17 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.vcs.log.VcsLogBundle;
|
||||
import com.intellij.vcs.log.VcsLogDataKeys;
|
||||
import com.intellij.vcs.log.VcsLogParentFilter;
|
||||
import com.intellij.vcs.log.VcsLogUi;
|
||||
import com.intellij.vcs.log.graph.PermanentGraph;
|
||||
import com.intellij.vcs.log.impl.MainVcsLogUiProperties;
|
||||
import com.intellij.vcs.log.impl.VcsLogIcons;
|
||||
import com.intellij.vcs.log.impl.VcsLogUiProperties;
|
||||
import com.intellij.vcs.log.ui.VcsLogActionIds;
|
||||
import com.intellij.vcs.log.ui.VcsLogInternalDataKeys;
|
||||
import com.intellij.vcs.log.util.BekUtil;
|
||||
import com.intellij.vcs.log.util.GraphOptionsUtil;
|
||||
import com.intellij.vcs.log.visible.filters.VcsLogParentFilterImplKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -25,6 +28,16 @@ import java.util.List;
|
||||
|
||||
public class VcsLogGraphOptionsChooserGroup extends DefaultActionGroup implements DumbAware {
|
||||
|
||||
private final @NotNull ParentFilterModel myParentFilterModel;
|
||||
|
||||
public VcsLogGraphOptionsChooserGroup(@NotNull ParentFilterModel parentFilterModel) {
|
||||
super(VcsLogBundle.message("group.Vcs.Log.GraphOptionsGroup.text"),
|
||||
VcsLogBundle.message("group.Vcs.Log.GraphOptionsGroup.description"),
|
||||
VcsLogIcons.IntelliSort);
|
||||
myParentFilterModel = parentFilterModel;
|
||||
setPopup(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnAction @NotNull [] getChildren(@Nullable AnActionEvent e) {
|
||||
if (e == null) return EMPTY_ARRAY;
|
||||
@@ -46,6 +59,7 @@ public class VcsLogGraphOptionsChooserGroup extends DefaultActionGroup implement
|
||||
actions.add(new SelectNonBaseOptionsAction(logUI, properties, PermanentGraph.Options.LinearBek.INSTANCE));
|
||||
}
|
||||
actions.add(new SelectNonBaseOptionsAction(logUI, properties, PermanentGraph.Options.FirstParent.INSTANCE));
|
||||
actions.add(new NoMergesFilterAction(myParentFilterModel));
|
||||
|
||||
actions.add(ActionManager.getInstance().getAction(VcsLogActionIds.BRANCH_ACTIONS_GROUP));
|
||||
|
||||
@@ -61,7 +75,7 @@ public class VcsLogGraphOptionsChooserGroup extends DefaultActionGroup implement
|
||||
if (isEnabled) {
|
||||
Icon icon = getTemplatePresentation().getIcon();
|
||||
if (icon != null) {
|
||||
if (!PermanentGraph.Options.Default.equals(properties.get(MainVcsLogUiProperties.GRAPH_OPTIONS))) {
|
||||
if (hasNonDefaultOptions(properties)) {
|
||||
e.getPresentation().setIcon(IconManager.getInstance().withIconBadge(icon, JBUI.CurrentTheme.IconBadge.SUCCESS));
|
||||
}
|
||||
else {
|
||||
@@ -76,6 +90,13 @@ public class VcsLogGraphOptionsChooserGroup extends DefaultActionGroup implement
|
||||
return ActionUpdateThread.EDT;
|
||||
}
|
||||
|
||||
private boolean hasNonDefaultOptions(@NotNull VcsLogUiProperties properties) {
|
||||
VcsLogParentFilter parentFilter = myParentFilterModel.getFilter();
|
||||
if (parentFilter != null && !VcsLogParentFilterImplKt.getMatchesAll(parentFilter)) return true;
|
||||
PermanentGraph.Options options = properties.get(MainVcsLogUiProperties.GRAPH_OPTIONS);
|
||||
return !PermanentGraph.Options.Default.equals(options);
|
||||
}
|
||||
|
||||
private static @NotNull List<PermanentGraph.SortType> getAvailableSortTypes() {
|
||||
List<PermanentGraph.SortType> sortTypes = new ArrayList<>(PermanentGraph.SortType.getEntries());
|
||||
if (!BekUtil.isBekEnabled()) {
|
||||
@@ -17,6 +17,8 @@ import com.intellij.vcs.log.data.index.IndexDataGetter
|
||||
import com.intellij.vcs.log.data.index.VcsLogIndex
|
||||
import com.intellij.vcs.log.graph.PermanentGraph
|
||||
import com.intellij.vcs.log.graph.VisibleGraph
|
||||
import com.intellij.vcs.log.graph.api.EdgeFilter
|
||||
import com.intellij.vcs.log.graph.api.LinearGraph
|
||||
import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo
|
||||
import com.intellij.vcs.log.graph.impl.facade.LinearGraphController
|
||||
import com.intellij.vcs.log.graph.impl.facade.PermanentGraphImpl
|
||||
@@ -34,6 +36,7 @@ import com.intellij.vcs.log.util.VcsLogUtil.FULL_HASH_LENGTH
|
||||
import com.intellij.vcs.log.visible.filters.*
|
||||
import io.opentelemetry.api.trace.Span
|
||||
import io.opentelemetry.api.trace.StatusCode
|
||||
import it.unimi.dsi.fastutil.ints.IntConsumer
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
|
||||
import it.unimi.dsi.fastutil.ints.IntSet
|
||||
import java.util.function.BiConsumer
|
||||
@@ -75,43 +78,27 @@ class VcsLogFiltererImpl(private val logProviders: Map<VirtualFile, VcsLogProvid
|
||||
val visibleRoots = VcsLogUtil.getAllVisibleRoots(dataPack.logProviders.keys, filters)
|
||||
|
||||
val matchingHeads: Set<Int>?
|
||||
val commitCandidates: IntSet?
|
||||
val forceFilterByVcs: Boolean
|
||||
var commitCandidates: IntSet? = null
|
||||
var forceFilterByVcs = false
|
||||
|
||||
val rangeFilters = allFilters.get(VcsLogFilterCollection.RANGE_FILTER)
|
||||
if (rangeFilters != null) {
|
||||
/*
|
||||
If we have both a range filter and a branch filter (e.g. `183\nmaster..feature`) they should be united: the graph should show both
|
||||
commits contained in the range, and commits reachable from branches.
|
||||
val (commits, heads) = filterByRange(dataPack, filters, visibleRoots, rangeFilters)
|
||||
|
||||
But the main filtering logic is opposite: matchingHeads + some other filter => makes the intersection of commits.
|
||||
To overcome this logic for the range filter case, we are not using matchingHeads, but are collecting all commits reachable from
|
||||
matchingHeads, and unite them with commits belonging to the range.
|
||||
*/
|
||||
val branchFilter = filters.get(VcsLogFilterCollection.BRANCH_FILTER)
|
||||
val revisionFilter = filters.get(VcsLogFilterCollection.REVISION_FILTER)
|
||||
val explicitMatchingHeads = getMatchingHeads(dataPack.refsModel, visibleRoots, branchFilter, revisionFilter)
|
||||
val commitsReachableFromHeads = if (explicitMatchingHeads != null)
|
||||
collectCommitsReachableFromHeads(dataPack, explicitMatchingHeads)
|
||||
else IntOpenHashSet()
|
||||
|
||||
commitCandidates = when (val commitsForRangeFilter = filterByRange(storage, logProviders, dataPack, rangeFilters)) {
|
||||
is RangeFilterResult.Commits -> IntCollectionUtil.union(listOf(commitsReachableFromHeads, commitsForRangeFilter.commits))
|
||||
RangeFilterResult.Error, RangeFilterResult.InvalidRange -> null
|
||||
}
|
||||
forceFilterByVcs = commitCandidates == null
|
||||
|
||||
/*
|
||||
At the same time, the root filter should intersect with the range filter (and the branch filter),
|
||||
therefore we take matching heads from the root filter, but use reachable commits set for the branch filter.
|
||||
*/
|
||||
matchingHeads = getMatchingHeads(dataPack.refsModel, visibleRoots)
|
||||
commitCandidates = commits
|
||||
matchingHeads = heads
|
||||
forceFilterByVcs = commits == null
|
||||
}
|
||||
else {
|
||||
commitCandidates = null
|
||||
forceFilterByVcs = false
|
||||
matchingHeads = getMatchingHeads(dataPack.refsModel, visibleRoots, filters)
|
||||
}
|
||||
|
||||
val parentFilter = allFilters.get(VcsLogFilterCollection.PARENT_FILTER)
|
||||
if (parentFilter != null && !parentFilter.matchesAll) {
|
||||
commitCandidates = filterByParent(dataPack, parentFilter, commitCandidates)
|
||||
forceFilterByVcs = commitCandidates == null
|
||||
}
|
||||
|
||||
try {
|
||||
val filterResult = filterByDetails(dataPack, filters, commitCount, visibleRoots, matchingHeads, commitCandidates, graphOptions, forceFilterByVcs)
|
||||
|
||||
@@ -345,6 +332,57 @@ class VcsLogFiltererImpl(private val logProviders: Map<VirtualFile, VcsLogProvid
|
||||
return VcsLogFilterObject.fromPatternsList(ArrayList(hashes), false)
|
||||
}
|
||||
|
||||
private fun filterByRange(dataPack: DataPack, filters: VcsLogFilterCollection, visibleRoots: Set<VirtualFile>,
|
||||
rangeFilter: VcsLogRangeFilter): Pair<IntSet?, Set<Int>> {
|
||||
/*
|
||||
If we have both a range filter and a branch filter (e.g. `183\nmaster..feature`) they should be united: the graph should show both
|
||||
commits contained in the range, and commits reachable from branches.
|
||||
|
||||
But the main filtering logic is opposite: matchingHeads + some other filter => makes the intersection of commits.
|
||||
To overcome this logic for the range filter case, we are not using matchingHeads, but are collecting all commits reachable from
|
||||
matchingHeads, and unite them with commits belonging to the range.
|
||||
*/
|
||||
val branchFilter = filters.get(VcsLogFilterCollection.BRANCH_FILTER)
|
||||
val revisionFilter = filters.get(VcsLogFilterCollection.REVISION_FILTER)
|
||||
val explicitMatchingHeads = getMatchingHeads(dataPack.refsModel, visibleRoots, branchFilter, revisionFilter)
|
||||
val commitsReachableFromHeads = if (explicitMatchingHeads != null)
|
||||
collectCommitsReachableFromHeads(dataPack, explicitMatchingHeads)
|
||||
else IntOpenHashSet()
|
||||
|
||||
val commits = when (val commitsForRangeFilter = filterByRange(storage, logProviders, dataPack, rangeFilter)) {
|
||||
is RangeFilterResult.Commits -> IntCollectionUtil.union(listOf(commitsReachableFromHeads, commitsForRangeFilter.commits))
|
||||
RangeFilterResult.Error, RangeFilterResult.InvalidRange -> null
|
||||
}
|
||||
|
||||
/*
|
||||
At the same time, the root filter should intersect with the range filter (and the branch filter),
|
||||
therefore we take matching heads from the root filter, but use reachable commits set for the branch filter.
|
||||
*/
|
||||
val heads = getMatchingHeads(dataPack.refsModel, visibleRoots)
|
||||
return Pair(commits, heads)
|
||||
}
|
||||
|
||||
private fun filterByParent(dataPack: DataPack, parentFilter: VcsLogParentFilter, commitCandidates: IntSet?): IntSet? {
|
||||
val result = IntOpenHashSet()
|
||||
@Suppress("UNCHECKED_CAST") val permanentGraph = dataPack.permanentGraph as? PermanentGraphInfo<Int> ?: return null
|
||||
if (commitCandidates != null) {
|
||||
commitCandidates.forEach(IntConsumer { commit ->
|
||||
val nodeId = permanentGraph.permanentCommitsInfo.getNodeId(commit)
|
||||
if (matches(permanentGraph.linearGraph, nodeId, parentFilter)) {
|
||||
result.add(commit)
|
||||
}
|
||||
})
|
||||
}
|
||||
else {
|
||||
for (nodeId in 0 until permanentGraph.linearGraph.nodesCount()) {
|
||||
if (matches(permanentGraph.linearGraph, nodeId, parentFilter)) {
|
||||
result.add(permanentGraph.permanentCommitsInfo.getCommitId(nodeId))
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun getMatchingHeads(refs: RefsModel,
|
||||
roots: Collection<VirtualFile>,
|
||||
filters: VcsLogFilterCollection): Set<Int>? {
|
||||
@@ -495,6 +533,11 @@ fun areFiltersAffectedByIndexing(filters: VcsLogFilterCollection, roots: List<Vi
|
||||
return needsIndex
|
||||
}
|
||||
|
||||
private fun matches(linearGraph: LinearGraph, node: Int, filter: VcsLogParentFilter): Boolean {
|
||||
val parentsCount = linearGraph.getAdjacentEdges(node, EdgeFilter.NORMAL_DOWN).size
|
||||
return parentsCount in filter.minParents..filter.maxParents
|
||||
}
|
||||
|
||||
internal fun <T> Collection<T>?.matchesNothing(): Boolean {
|
||||
return this != null && this.isEmpty()
|
||||
}
|
||||
|
||||
@@ -195,6 +195,16 @@ object VcsLogFilterObject {
|
||||
return VcsLogRootFilterImpl(roots)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun noMerges(): VcsLogParentFilter {
|
||||
return fromParentCount(maxParents = 1)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromParentCount(minParents: Int? = null, maxParents: Int? = null): VcsLogParentFilter {
|
||||
return VcsLogParentFilterImpl(minParents ?: 0, maxParents ?: Int.MAX_VALUE)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun collection(vararg filters: VcsLogFilter?): VcsLogFilterCollection {
|
||||
val filterSet = createFilterSet()
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.vcs.log.visible.filters
|
||||
|
||||
import com.intellij.vcs.log.VcsLogParentFilter
|
||||
|
||||
internal class VcsLogParentFilterImpl(override val minParents: Int = 0, override val maxParents: Int = Int.MAX_VALUE) : VcsLogParentFilter {
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
override fun getDisplayText(): String {
|
||||
if (isNoMerges) return "--no-merges"
|
||||
return buildString {
|
||||
if (hasLowerBound) append("--min-parents=$minParents")
|
||||
if (hasUpperBound) append("--max-parents=$maxParents")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val VcsLogParentFilter.hasLowerBound get() = minParents > 0
|
||||
val VcsLogParentFilter.hasUpperBound get() = maxParents != Int.MAX_VALUE
|
||||
|
||||
val VcsLogParentFilter.matchesAll: Boolean get() = minParents <= 0 && maxParents == Int.MAX_VALUE
|
||||
val VcsLogParentFilter.isNoMerges: Boolean get() = maxParents == 1 && !hasLowerBound
|
||||
@@ -30,6 +30,7 @@ import com.intellij.vcs.log.util.UserNameRegex;
|
||||
import com.intellij.vcs.log.util.VcsUserUtil;
|
||||
import com.intellij.vcs.log.visible.CommitCountStageKt;
|
||||
import com.intellij.vcs.log.visible.filters.VcsLogFiltersKt;
|
||||
import com.intellij.vcs.log.visible.filters.VcsLogParentFilterImplKt;
|
||||
import com.intellij.vcsUtil.VcsFileUtil;
|
||||
import git4idea.*;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
@@ -479,6 +480,12 @@ public final class GitLogProvider implements VcsLogProvider, VcsIndexableLogProv
|
||||
filterParameters.add("--first-parent");
|
||||
}
|
||||
|
||||
VcsLogParentFilter parentFilter = filterCollection.get(PARENT_FILTER);
|
||||
if (parentFilter != null && !VcsLogParentFilterImplKt.getMatchesAll(parentFilter)) {
|
||||
if (VcsLogParentFilterImplKt.getHasLowerBound(parentFilter)) filterParameters.add("--min-parents=" + parentFilter.getMinParents());
|
||||
if (VcsLogParentFilterImplKt.getHasUpperBound(parentFilter)) filterParameters.add("--max-parents=" + parentFilter.getMaxParents());
|
||||
}
|
||||
|
||||
// note: structure filter must be the last parameter, because it uses "--" which separates parameters from paths
|
||||
VcsLogStructureFilter structureFilter = filterCollection.get(STRUCTURE_FILTER);
|
||||
if (structureFilter != null) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.zmlx.hg4idea.log;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
@@ -317,7 +317,7 @@ public final class HgLogProvider implements VcsLogProvider {
|
||||
|
||||
@Override
|
||||
public @Nullable <T> T getPropertyValue(VcsLogProperties.VcsLogProperty<T> property) {
|
||||
if (property == VcsLogProperties.CASE_INSENSITIVE_REGEX) {
|
||||
if (property == VcsLogProperties.CASE_INSENSITIVE_REGEX || property == VcsLogProperties.SUPPORTS_PARENTS_FILTER) {
|
||||
return (T)Boolean.FALSE;
|
||||
}
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user