Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions src/Commands/QueryDiffLineStats.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.Text;
using System.Threading.Tasks;

namespace SourceGit.Commands
{
public class QueryDiffLineStats : Command
{
public QueryDiffLineStats(string repo, string start, string end, bool ignoreWhitespace, bool ignoreCRAtEOL)
: this(repo, ignoreWhitespace, ignoreCRAtEOL, $"{(string.IsNullOrEmpty(start) ? "-R" : start)} {end}")
{
}

public QueryDiffLineStats(string repo, bool staged, bool ignoreWhitespace, bool ignoreCRAtEOL)
: this(repo, ignoreWhitespace, ignoreCRAtEOL, staged ? "--cached" : string.Empty)
{
}

private QueryDiffLineStats(string repo, bool ignoreWhitespace, bool ignoreCRAtEOL, string suffix)
{
WorkingDirectory = repo;
Context = repo;
RaiseError = false;

var builder = new StringBuilder();
builder.Append("diff --no-color --no-ext-diff --numstat -z ");
if (ignoreCRAtEOL)
builder.Append("--ignore-cr-at-eol ");
if (ignoreWhitespace)
builder.Append("--ignore-space-change --ignore-blank-lines ");
builder.Append(suffix);
Args = builder.ToString().TrimEnd();
}

public async Task<(int added, int deleted)> GetResultAsync()
{
try
{
var rs = await ReadToEndAsync().ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(rs.StdOut))
return (0, 0);

int added = 0, deleted = 0;
foreach (var token in rs.StdOut.Split('\0', StringSplitOptions.RemoveEmptyEntries))
{
var parts = token.Split('\t', 3);
if (parts.Length < 2)
continue;

added += ParseCount(parts[0]);
deleted += ParseCount(parts[1]);
}

return (added, deleted);
}
catch
{
return (0, 0);
}
}

private static int ParseCount(string value) => int.TryParse(value, out var parsed) ? parsed : 0;
}
}
19 changes: 19 additions & 0 deletions src/ViewModels/CommitDetail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ public List<Models.Change> VisibleChanges
set => SetProperty(ref _visibleChanges, value);
}

public int TotalAddedLines
{
get => _totalAddedLines;
private set => SetProperty(ref _totalAddedLines, value);
}

public int TotalDeletedLines
{
get => _totalDeletedLines;
private set => SetProperty(ref _totalDeletedLines, value);
}

public List<Models.Change> SelectedChanges
{
get => _selectedChanges;
Expand Down Expand Up @@ -534,6 +546,9 @@ private void Refresh()
{
var cmd = new Commands.CompareRevisions(_repo.FullPath, _commit.FirstParentToCompare, _commit.SHA) { CancellationToken = token };
var changes = await cmd.ReadAsync().ConfigureAwait(false);
var pref = Preferences.Instance;
var statsCmd = new Commands.QueryDiffLineStats(_repo.FullPath, _commit.FirstParentToCompare, _commit.SHA, pref.IgnoreWhitespaceChangesInDiff, pref.IgnoreCRAtEOLInDiff) { CancellationToken = token };
var stats = await statsCmd.GetResultAsync().ConfigureAwait(false);
var visible = changes;
if (!string.IsNullOrWhiteSpace(_searchChangeFilter))
{
Expand All @@ -551,6 +566,8 @@ private void Refresh()
{
Changes = changes;
VisibleChanges = visible;
TotalAddedLines = stats.added;
TotalDeletedLines = stats.deleted;

if (visible.Count == 0)
SelectedChanges = null;
Expand Down Expand Up @@ -768,6 +785,8 @@ private async Task SetViewingCommitAsync(Models.Object file)
private List<Models.Change> _changes = [];
private List<Models.Change> _visibleChanges = [];
private List<Models.Change> _selectedChanges = null;
private int _totalAddedLines = 0;
private int _totalDeletedLines = 0;
private string _searchChangeFilter = string.Empty;
private DiffContext _diffContext = null;
private string _viewRevisionFilePath = string.Empty;
Expand Down
25 changes: 25 additions & 0 deletions src/ViewModels/Compare.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ public int TotalChanges
private set => SetProperty(ref _totalChanges, value);
}

public int TotalAddedLines
{
get => _totalAddedLines;
private set => SetProperty(ref _totalAddedLines, value);
}

public int TotalDeletedLines
{
get => _totalDeletedLines;
private set => SetProperty(ref _totalDeletedLines, value);
}

public List<Models.Change> VisibleChanges
{
get => _visibleChanges;
Expand Down Expand Up @@ -317,6 +329,15 @@ private void UpdateChanges()
.ReadAsync()
.ConfigureAwait(false);

var pref = Preferences.Instance;
var stats = await new Commands.QueryDiffLineStats(
_repo.FullPath,
_based,
_to,
pref.IgnoreWhitespaceChangesInDiff,
pref.IgnoreCRAtEOLInDiff)
.GetResultAsync().ConfigureAwait(false);

var visible = _changes;
if (!string.IsNullOrWhiteSpace(_searchFilter))
{
Expand All @@ -331,6 +352,8 @@ private void UpdateChanges()
Dispatcher.UIThread.Post(() =>
{
TotalChanges = _changes.Count;
TotalAddedLines = stats.added;
TotalDeletedLines = stats.deleted;
VisibleChanges = visible;
IsLoadingChanges = false;

Expand Down Expand Up @@ -398,6 +421,8 @@ private string GetSHA(object obj)
private Models.Commit _baseHead = null;
private Models.Commit _toHead = null;
private int _totalChanges = 0;
private int _totalAddedLines = 0;
private int _totalDeletedLines = 0;
private List<Models.Change> _changes = null;
private List<Models.Change> _visibleChanges = null;
private List<Models.Change> _selectedChanges = null;
Expand Down
29 changes: 28 additions & 1 deletion src/ViewModels/RevisionCompare.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ public int TotalChanges
private set => SetProperty(ref _totalChanges, value);
}

public int TotalAddedLines
{
get => _totalAddedLines;
private set => SetProperty(ref _totalAddedLines, value);
}

public int TotalDeletedLines
{
get => _totalDeletedLines;
private set => SetProperty(ref _totalDeletedLines, value);
}

public List<Models.Change> VisibleChanges
{
get => _visibleChanges;
Expand Down Expand Up @@ -350,10 +362,21 @@ private void Refresh()
{
Task.Run(async () =>
{
_changes = await new Commands.CompareRevisions(_repo.FullPath, GetSHA(_startPoint), GetSHA(_endPoint))
var startSHA = GetSHA(_startPoint);
var endSHA = GetSHA(_endPoint);
_changes = await new Commands.CompareRevisions(_repo.FullPath, startSHA, endSHA)
.ReadAsync()
.ConfigureAwait(false);

var pref = Preferences.Instance;
var stats = await new Commands.QueryDiffLineStats(
_repo.FullPath,
startSHA,
endSHA,
pref.IgnoreWhitespaceChangesInDiff,
pref.IgnoreCRAtEOLInDiff)
.GetResultAsync().ConfigureAwait(false);

var visible = _changes;
if (!string.IsNullOrWhiteSpace(_searchFilter))
{
Expand All @@ -368,6 +391,8 @@ private void Refresh()
Dispatcher.UIThread.Post(() =>
{
TotalChanges = _changes.Count;
TotalAddedLines = stats.added;
TotalDeletedLines = stats.deleted;
VisibleChanges = visible;
IsLoading = false;

Expand All @@ -394,6 +419,8 @@ private string GetDesc(object obj)
private object _startPoint = null;
private object _endPoint = null;
private int _totalChanges = 0;
private int _totalAddedLines = 0;
private int _totalDeletedLines = 0;
private List<Models.Change> _changes = null;
private List<Models.Change> _visibleChanges = null;
private List<Models.Change> _selectedChanges = null;
Expand Down
52 changes: 52 additions & 0 deletions src/ViewModels/WorkingCopy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;

namespace SourceGit.ViewModels
Expand Down Expand Up @@ -160,6 +161,30 @@ public List<Models.Change> VisibleStaged
private set => SetProperty(ref _visibleStaged, value);
}

public int UnstagedAddedLines
{
get => _unstagedAddedLines;
private set => SetProperty(ref _unstagedAddedLines, value);
}

public int UnstagedDeletedLines
{
get => _unstagedDeletedLines;
private set => SetProperty(ref _unstagedDeletedLines, value);
}

public int StagedAddedLines
{
get => _stagedAddedLines;
private set => SetProperty(ref _stagedAddedLines, value);
}

public int StagedDeletedLines
{
get => _stagedDeletedLines;
private set => SetProperty(ref _stagedDeletedLines, value);
}

public List<Models.Change> SelectedUnstaged
{
get => _selectedUnstaged;
Expand Down Expand Up @@ -312,6 +337,29 @@ public void SetData(List<Models.Change> changes)

UpdateInProgressState();
UpdateDetail();

_ = Task.Run(async () =>
{
var pref = Preferences.Instance;
var unstagedStats = await new Commands.QueryDiffLineStats(
_repo.FullPath, false, pref.IgnoreWhitespaceChangesInDiff, pref.IgnoreCRAtEOLInDiff)
.GetResultAsync().ConfigureAwait(false);
var stagedStats = await new Commands.QueryDiffLineStats(
_repo.FullPath, true, pref.IgnoreWhitespaceChangesInDiff, pref.IgnoreCRAtEOLInDiff)
.GetResultAsync().ConfigureAwait(false);

Dispatcher.UIThread.Post(() =>
{
// A newer SetData may have run while fetching stats; drop this stale update.
if (!ReferenceEquals(_cached, changes))
return;

UnstagedAddedLines = unstagedStats.added;
UnstagedDeletedLines = unstagedStats.deleted;
StagedAddedLines = stagedStats.added;
StagedDeletedLines = stagedStats.deleted;
});
});
}

public async Task StageChangesAsync(List<Models.Change> changes, Models.Change next)
Expand Down Expand Up @@ -821,6 +869,10 @@ private bool IsChanged(List<Models.Change> old, List<Models.Change> cur)
private List<Models.Change> _visibleStaged = [];
private List<Models.Change> _selectedUnstaged = [];
private List<Models.Change> _selectedStaged = [];
private int _unstagedAddedLines = 0;
private int _unstagedDeletedLines = 0;
private int _stagedAddedLines = 0;
private int _stagedDeletedLines = 0;
private object _detailContext = null;
private string _filter = string.Empty;
private string _commitMessage = string.Empty;
Expand Down
25 changes: 19 additions & 6 deletions src/Views/CommitChanges.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.CommitChanges"
x:DataType="vm:CommitDetail">
Expand Down Expand Up @@ -56,12 +57,24 @@

<!-- Summary -->
<Border Grid.Row="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1,0,1,1" Background="Transparent">
<TextBlock Margin="4,0,0,0"
Foreground="{DynamicResource Brush.FG2}"
HorizontalAlignment="Left" VerticalAlignment="Center">
<Run Text="{Binding Changes.Count, Mode=OneWay}" FontWeight="Bold"/>
<Run Text="{DynamicResource Text.CommitDetail.Changes.Count}"/>
</TextBlock>
<StackPanel Orientation="Horizontal" Margin="4,0,0,0" VerticalAlignment="Center">
<TextBlock Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Left" VerticalAlignment="Center">
<Run Text="{Binding Changes.Count, Mode=OneWay}" FontWeight="Bold"/>
<Run Text="{DynamicResource Text.CommitDetail.Changes.Count}"/>
</TextBlock>
<TextBlock FontSize="11"
Margin="12,0,0,0"
Foreground="Green"
Text="{Binding TotalAddedLines, StringFormat=+{0}}"
IsVisible="{Binding TotalAddedLines, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"
VerticalAlignment="Center"/>
<TextBlock FontSize="11"
Margin="4,0,0,0"
Foreground="Red"
Text="{Binding TotalDeletedLines, StringFormat=-{0}}"
IsVisible="{Binding TotalDeletedLines, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
</Grid>

Expand Down
24 changes: 18 additions & 6 deletions src/Views/Compare.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,24 @@

<!-- Summary -->
<Border Grid.Row="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1,0,1,1" Background="Transparent">
<TextBlock Margin="4,0,0,0"
Foreground="{DynamicResource Brush.FG2}"
HorizontalAlignment="Left" VerticalAlignment="Center">
<Run Text="{Binding TotalChanges, Mode=OneWay}" FontWeight="Bold"/>
<Run Text="{DynamicResource Text.CommitDetail.Changes.Count}"/>
</TextBlock>
<StackPanel Orientation="Horizontal" Margin="4,0,0,0" VerticalAlignment="Center">
<TextBlock Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Left" VerticalAlignment="Center">
<Run Text="{Binding TotalChanges, Mode=OneWay}" FontWeight="Bold"/>
<Run Text="{DynamicResource Text.CommitDetail.Changes.Count}"/>
</TextBlock>
<TextBlock FontSize="11"
Margin="12,0,0,0"
Foreground="Green"
Text="{Binding TotalAddedLines, StringFormat=+{0}}"
IsVisible="{Binding TotalAddedLines, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"
VerticalAlignment="Center"/>
<TextBlock FontSize="11"
Margin="4,0,0,0"
Foreground="Red"
Text="{Binding TotalDeletedLines, StringFormat=-{0}}"
IsVisible="{Binding TotalDeletedLines, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
</Grid>

Expand Down
Loading
Loading