Show the list of children in the commit details (#710)

* feature: add children list to the commit base info view

Useful for navigation between the commits.

* feature: use repository filters to limit children search
* feature: execute children search asynchronously
* feature: respect global commit limit for a good measure
* fix: input lines may contain several commits

The first commit is always the immediate child, so take only 40 initial characters of the line

* fix: hide children behind the preference
* feature: make parents and children scrollable
This commit is contained in:
Dmitrij D. Czarkoff 2024-11-20 01:17:36 +00:00 committed by GitHub
parent cc1eb55cf0
commit cc5bb5f6d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 170 additions and 44 deletions

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using SourceGit.ViewModels;
namespace SourceGit.Commands
{
public class QueryCommitChildren : Command
{
public QueryCommitChildren(string repo, string commit, string filters)
{
WorkingDirectory = repo;
Context = repo;
_commit = commit;
if (string.IsNullOrEmpty(filters))
filters = "--all";
Args = $"rev-list -{Preference.Instance.MaxHistoryCommits} --parents {filters} ^{commit}";
}
protected override void OnReadline(string line)
{
if (line.Contains(_commit))
_lines.Add(line.Substring(0, 40));
}
public IEnumerable<string> Result()
{
Exec();
return _lines;
}
private string _commit;
private List<string> _lines = new List<string>();
}
}

View file

@ -125,6 +125,7 @@
<x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMATION</x:String> <x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMATION</x:String>
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTHOR</x:String> <x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTHOR</x:String>
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CHANGED</x:String> <x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CHANGED</x:String>
<x:String x:Key="Text.CommitDetail.Info.Children" xml:space="preserve">CHILDREN</x:String>
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String> <x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Check refs that contains this commit</x:String> <x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Check refs that contains this commit</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">COMMIT IS CONTAINED BY</x:String> <x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">COMMIT IS CONTAINED BY</x:String>
@ -451,6 +452,7 @@
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Language</x:String> <x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Language</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String> <x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
<x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">Show author time intead of commit time in graph</x:String> <x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">Show author time intead of commit time in graph</x:String>
<x:String x:Key="Text.Preference.General.ShowChildren" xml:space="preserve">Show children in the comment details</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String> <x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Enable Auto CRLF</x:String> <x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Enable Auto CRLF</x:String>

View file

@ -126,6 +126,7 @@
<x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMATIONS</x:String> <x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMATIONS</x:String>
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTEUR</x:String> <x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTEUR</x:String>
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CHANGÉ</x:String> <x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CHANGÉ</x:String>
<x:String x:Key="Text.CommitDetail.Info.Children" xml:space="preserve">ENFANTS</x:String>
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String> <x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Vérifier les références contenant ce commit</x:String> <x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Vérifier les références contenant ce commit</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">LE COMMIT EST CONTENU PAR</x:String> <x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">LE COMMIT EST CONTENU PAR</x:String>

View file

@ -78,6 +78,12 @@ namespace SourceGit.ViewModels
} }
} }
public AvaloniaList<string> Children
{
get;
private set;
} = new AvaloniaList<string>();
public string SearchChangeFilter public string SearchChangeFilter
{ {
get => _searchChangeFilter; get => _searchChangeFilter;
@ -515,6 +521,7 @@ namespace SourceGit.ViewModels
VisibleChanges = null; VisibleChanges = null;
SelectedChanges = null; SelectedChanges = null;
ViewRevisionFileContent = null; ViewRevisionFileContent = null;
Children.Clear();
if (_commit == null) if (_commit == null)
return; return;
@ -535,6 +542,18 @@ namespace SourceGit.ViewModels
_cancelToken.Requested = true; _cancelToken.Requested = true;
_cancelToken = new Commands.Command.CancelToken(); _cancelToken = new Commands.Command.CancelToken();
if (Preference.Instance.ShowChildren)
{
Task.Run(() =>
{
var cmdChildren = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, _repo.Settings.BuildHistoriesFilter()) { Cancel = _cancelToken };
var children = cmdChildren.Result();
if (!cmdChildren.Cancel.Requested)
Dispatcher.UIThread.Post(() => Children.AddRange(children));
});
}
Task.Run(() => Task.Run(() =>
{ {
var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0]; var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0];

View file

@ -294,6 +294,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _statisticsSampleColor, value); set => SetProperty(ref _statisticsSampleColor, value);
} }
public bool ShowChildren
{
get => _showChildren;
set => SetProperty(ref _showChildren, value);
}
public List<RepositoryNode> RepositoryNodes public List<RepositoryNode> RepositoryNodes
{ {
get; get;
@ -617,5 +623,7 @@ namespace SourceGit.ViewModels
private string _externalMergeToolPath = string.Empty; private string _externalMergeToolPath = string.Empty;
private uint _statisticsSampleColor = 0xFF00FF00; private uint _statisticsSampleColor = 0xFF00FF00;
private bool _showChildren = false;
} }
} }

View file

@ -51,7 +51,7 @@
<Rectangle Height=".65" Margin="8" Fill="{DynamicResource Brush.Border2}" VerticalAlignment="Center"/> <Rectangle Height=".65" Margin="8" Fill="{DynamicResource Brush.Border2}" VerticalAlignment="Center"/>
<!-- Base Information --> <!-- Base Information -->
<Grid RowDefinitions="24,Auto,Auto,Auto" ColumnDefinitions="96,*"> <Grid RowDefinitions="24,Auto,Auto,Auto,Auto" ColumnDefinitions="96,*">
<!-- SHA --> <!-- SHA -->
<TextBlock Grid.Row="0" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.SHA}" /> <TextBlock Grid.Row="0" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.SHA}" />
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal"> <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
@ -102,7 +102,8 @@
<!-- PARENTS --> <!-- PARENTS -->
<TextBlock Grid.Row="1" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.Parents}" IsVisible="{Binding Parents.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"/> <TextBlock Grid.Row="1" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.Parents}" IsVisible="{Binding Parents.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"/>
<ItemsControl Grid.Row="1" Grid.Column="1" Height="24" Margin="12,0,0,0" ItemsSource="{Binding Parents}" IsVisible="{Binding Parents.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"> <ScrollViewer Grid.Row="1" Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden" AllowAutoHide="True">
<ItemsControl Height="24" Margin="12,0,0,0" ItemsSource="{Binding Parents}" IsVisible="{Binding Parents.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"/> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"/>
@ -142,10 +143,56 @@
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>
</ScrollViewer>
<!-- CHILDREN -->
<TextBlock Grid.Row="2" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.Children}" IsVisible="{Binding #ThisControl.Children.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"/>
<ScrollViewer Grid.Row="2" Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden" AllowAutoHide="True">
<ItemsControl Height="24" Margin="12,0,0,0" ItemsSource="{Binding #ThisControl.Children}" IsVisible="{Binding #ThisControl.Children.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Classes="primary"
Text="{Binding Converter={x:Static c:StringConverters.ToShortSHA}}"
Foreground="DarkOrange"
TextDecorations="Underline"
Cursor="Hand"
Margin="0,0,16,0"
PointerEntered="OnSHAPointerEntered"
PointerPressed="OnSHAPressed">
<TextBlock.Styles>
<Style Selector="ToolTip">
<Setter Property="MaxWidth" Value="600"/>
</Style>
</TextBlock.Styles>
<TextBlock.DataTemplates>
<DataTemplate DataType="m:Commit">
<StackPanel MinWidth="400" Orientation="Vertical">
<Grid ColumnDefinitions="Auto,*,Auto">
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
<TextBlock Grid.Column="1" Classes="primary" Text="{Binding Author.Name}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2" Classes="primary" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
</Grid>
<TextBlock Classes="primary" Margin="0,8,0,0" Text="{Binding Subject}" TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
</TextBlock.DataTemplates>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- REFS --> <!-- REFS -->
<TextBlock Grid.Row="2" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.Refs}" IsVisible="{Binding HasDecorators}"/> <TextBlock Grid.Row="3" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.Refs}" IsVisible="{Binding HasDecorators}"/>
<Border Grid.Row="2" Grid.Column="1" Margin="12,0,0,0" Height="24" IsVisible="{Binding HasDecorators}"> <Border Grid.Row="3" Grid.Column="1" Margin="12,0,0,0" Height="24" IsVisible="{Binding HasDecorators}">
<v:CommitRefsPresenter TagBackground="{DynamicResource Brush.DecoratorTag}" <v:CommitRefsPresenter TagBackground="{DynamicResource Brush.DecoratorTag}"
Foreground="{DynamicResource Brush.FG1}" Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}" FontFamily="{DynamicResource Fonts.Primary}"
@ -155,8 +202,8 @@
</Border> </Border>
<!-- Messages --> <!-- Messages -->
<TextBlock Grid.Row="3" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.Message}" VerticalAlignment="Top" Margin="0,4,0,0" /> <TextBlock Grid.Row="4" Grid.Column="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.Message}" VerticalAlignment="Top" Margin="0,4,0,0" />
<v:CommitMessagePresenter Grid.Row="4" Grid.Column="1" <v:CommitMessagePresenter Grid.Row="5" Grid.Column="1"
Margin="12,5,8,0" Margin="12,5,8,0"
Classes="primary" Classes="primary"
Message="{Binding #ThisControl.Message}" Message="{Binding #ThisControl.Message}"

View file

@ -55,6 +55,15 @@ namespace SourceGit.Views
set => SetValue(IssueTrackerRulesProperty, value); set => SetValue(IssueTrackerRulesProperty, value);
} }
public static readonly StyledProperty<AvaloniaList<string>> ChildrenProperty =
AvaloniaProperty.Register<CommitBaseInfo, AvaloniaList<string>>(nameof(Children));
public AvaloniaList<string> Children
{
get => GetValue(ChildrenProperty);
set => SetValue(ChildrenProperty, value);
}
public CommitBaseInfo() public CommitBaseInfo()
{ {
InitializeComponent(); InitializeComponent();

View file

@ -24,6 +24,7 @@
SignInfo="{Binding SignInfo}" SignInfo="{Binding SignInfo}"
SupportsContainsIn="True" SupportsContainsIn="True"
WebLinks="{Binding WebLinks}" WebLinks="{Binding WebLinks}"
Children="{Binding Children}"
IssueTrackerRules="{Binding IssueTrackerRules}"/> IssueTrackerRules="{Binding IssueTrackerRules}"/>
<!-- Line --> <!-- Line -->

View file

@ -45,7 +45,7 @@
<TabItem.Header> <TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="Auto,*"> <Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.Locale}" Text="{DynamicResource Text.Preference.General.Locale}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
@ -114,6 +114,11 @@
Height="32" Height="32"
Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}" Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/>
<CheckBox Grid.Row="6" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preference.General.ShowChildren}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowChildren, Mode=TwoWay}"/>
</Grid> </Grid>
</TabItem> </TabItem>