feature: allows to compare selected tag with current HEAD

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2026-01-05 15:05:35 +08:00
parent bfee290feb
commit 7043a22de6
7 changed files with 71 additions and 33 deletions

View File

@@ -853,6 +853,7 @@
<x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String>
<x:String x:Key="Text.Tag.Tagger" xml:space="preserve">TAGGER</x:String>
<x:String x:Key="Text.Tag.Time" xml:space="preserve">TIME</x:String>
<x:String x:Key="Text.TagCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String>
<x:String x:Key="Text.TagCM.Copy.Message" xml:space="preserve">Message</x:String>
<x:String x:Key="Text.TagCM.Copy.Name" xml:space="preserve">Name</x:String>
<x:String x:Key="Text.TagCM.Copy.Tagger" xml:space="preserve">Tagger</x:String>

View File

@@ -857,6 +857,7 @@
<x:String x:Key="Text.Sure" xml:space="preserve">确 定</x:String>
<x:String x:Key="Text.Tag.Tagger" xml:space="preserve">创建者</x:String>
<x:String x:Key="Text.Tag.Time" xml:space="preserve">创建时间</x:String>
<x:String x:Key="Text.TagCM.CompareWithHead" xml:space="preserve">与当前 HEAD 比较</x:String>
<x:String x:Key="Text.TagCM.Copy.Message" xml:space="preserve">标签信息</x:String>
<x:String x:Key="Text.TagCM.Copy.Name" xml:space="preserve">标签名</x:String>
<x:String x:Key="Text.TagCM.Copy.Tagger" xml:space="preserve">创建者</x:String>

View File

@@ -857,6 +857,7 @@
<x:String x:Key="Text.Sure" xml:space="preserve">確 定</x:String>
<x:String x:Key="Text.Tag.Tagger" xml:space="preserve">建立者</x:String>
<x:String x:Key="Text.Tag.Time" xml:space="preserve">建立時間</x:String>
<x:String x:Key="Text.TagCM.CompareWithHead" xml:space="preserve">與目前 HEAD 比較</x:String>
<x:String x:Key="Text.TagCM.Copy.Message" xml:space="preserve">標籤訊息</x:String>
<x:String x:Key="Text.TagCM.Copy.Name" xml:space="preserve">標籤名稱</x:String>
<x:String x:Key="Text.TagCM.Copy.Tagger" xml:space="preserve">建立者</x:String>

View File

@@ -8,27 +8,22 @@ namespace SourceGit.ViewModels
{
public class BranchCompare : ObservableObject
{
public string RepositoryPath
{
get => _repo;
}
public bool IsLoading
{
get => _isLoading;
private set => SetProperty(ref _isLoading, value);
}
public Models.Branch Base
public string BaseName
{
get => _based;
private set => SetProperty(ref _based, value);
get => _baseName;
private set => SetProperty(ref _baseName, value);
}
public Models.Branch To
public string ToName
{
get => _to;
private set => SetProperty(ref _to, value);
get => _toName;
private set => SetProperty(ref _toName, value);
}
public Models.Commit BaseHead
@@ -63,7 +58,7 @@ namespace SourceGit.ViewModels
if (SetProperty(ref _selectedChanges, value))
{
if (value is { Count: 1 })
DiffContext = new DiffContext(_repo, new Models.DiffOption(_based.Head, _to.Head, value[0]), _diffContext);
DiffContext = new DiffContext(_repo, new Models.DiffOption(_based, _to, value[0]), _diffContext);
else
DiffContext = null;
}
@@ -86,11 +81,13 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _diffContext, value);
}
public BranchCompare(string repo, Models.Branch baseBranch, Models.Branch toBranch)
public BranchCompare(string repo, object based, object to)
{
_repo = repo;
_based = baseBranch;
_to = toBranch;
_based = GetSHA(based);
_to = GetSHA(to);
_baseName = GetName(based);
_toName = GetName(to);
Refresh();
}
@@ -113,10 +110,8 @@ namespace SourceGit.ViewModels
public void Swap()
{
(Base, To) = (_to, _based);
VisibleChanges = [];
SelectedChanges = [];
(_based, _to) = (_to, _based);
(BaseName, ToName) = (_toName, _baseName);
if (_baseHead != null)
(BaseHead, ToHead) = (_toHead, _baseHead);
@@ -134,9 +129,14 @@ namespace SourceGit.ViewModels
return Native.OS.GetAbsPath(_repo, path);
}
public void OpenInExternalDiffTool(Models.Change change)
{
new Commands.DiffTool(_repo, new Models.DiffOption(_based, _to, change)).Open();
}
public async Task SaveChangesAsPatchAsync(List<Models.Change> changes, string saveTo)
{
var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo, changes, _based.Head, _to.Head, saveTo);
var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo, changes, _based, _to, saveTo);
if (succ)
App.SendNotification(_repo, App.Text("SaveAsPatchSuccess"));
}
@@ -144,16 +144,18 @@ namespace SourceGit.ViewModels
private void Refresh()
{
IsLoading = true;
VisibleChanges = [];
SelectedChanges = [];
Task.Run(async () =>
{
if (_baseHead == null)
{
var baseHead = await new Commands.QuerySingleCommit(_repo, _based.Head)
var baseHead = await new Commands.QuerySingleCommit(_repo, _based)
.GetResultAsync()
.ConfigureAwait(false);
var toHead = await new Commands.QuerySingleCommit(_repo, _to.Head)
var toHead = await new Commands.QuerySingleCommit(_repo, _to)
.GetResultAsync()
.ConfigureAwait(false);
@@ -164,7 +166,7 @@ namespace SourceGit.ViewModels
});
}
_changes = await new Commands.CompareRevisions(_repo, _based.Head, _to.Head)
_changes = await new Commands.CompareRevisions(_repo, _based, _to)
.ReadAsync()
.ConfigureAwait(false);
@@ -215,10 +217,34 @@ namespace SourceGit.ViewModels
}
}
private string GetName(object obj)
{
return obj switch
{
Models.Branch b => b.FriendlyName,
Models.Tag t => t.Name,
Models.Commit c => c.SHA.Substring(0, 10),
_ => "HEAD",
};
}
private string GetSHA(object obj)
{
return obj switch
{
Models.Branch b => b.Head,
Models.Tag t => t.SHA,
Models.Commit c => c.SHA,
_ => "HEAD",
};
}
private string _repo;
private bool _isLoading = true;
private Models.Branch _based = null;
private Models.Branch _to = null;
private string _based = string.Empty;
private string _to = string.Empty;
private string _baseName = string.Empty;
private string _toName = string.Empty;
private Models.Commit _baseHead = null;
private Models.Commit _toHead = null;
private int _totalChanges = 0;

View File

@@ -48,7 +48,7 @@
User="{Binding BaseHead.Author}"/>
<TextBlock Grid.Column="1" Text="{Binding BaseHead.Author.Name}" Margin="8,0,0,0"/>
<Border Grid.Column="2" Background="{DynamicResource Brush.Accent}" CornerRadius="4">
<TextBlock Text="{Binding Base.FriendlyName}" Margin="4,0" Foreground="#FFDDDDDD"/>
<TextBlock Text="{Binding BaseName}" Margin="4,0" Foreground="#FFDDDDDD"/>
</Border>
<TextBlock Grid.Column="3" Text="{Binding BaseHead.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" Cursor="Hand" PointerPressed="OnPressedSHA"/>
<TextBlock Grid.Column="4" Text="{Binding BaseHead.CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
@@ -72,7 +72,7 @@
User="{Binding ToHead.Author}"/>
<TextBlock Grid.Column="1" Text="{Binding ToHead.Author.Name}" Margin="8,0,0,0"/>
<Border Grid.Column="2" Background="{DynamicResource Brush.Accent}" CornerRadius="4">
<TextBlock Text="{Binding To.FriendlyName}" Margin="4,0" Foreground="#FFDDDDDD"/>
<TextBlock Text="{Binding ToName}" Margin="4,0" Foreground="#FFDDDDDD"/>
</Border>
<TextBlock Grid.Column="3" Text="{Binding ToHead.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" Cursor="Hand" PointerPressed="OnPressedSHA"/>
<TextBlock Grid.Column="4" Text="{Binding ToHead.CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>

View File

@@ -21,7 +21,6 @@ namespace SourceGit.Views
sender is ChangeCollectionView view)
{
var menu = new ContextMenu();
var repo = vm.RepositoryPath;
var patch = new MenuItem();
patch.Header = App.Text("FileCM.SaveAsPatch");
@@ -48,7 +47,7 @@ namespace SourceGit.Views
}
catch (Exception exception)
{
App.RaiseException(repo, $"Failed to save as patch: {exception.Message}");
App.RaiseException(null, $"Failed to save as patch: {exception.Message}");
}
e.Handled = true;
@@ -63,14 +62,14 @@ namespace SourceGit.Views
openWithMerger.Tag = OperatingSystem.IsMacOS() ? "⌘+⇧+D" : "Ctrl+Shift+D";
openWithMerger.Click += (_, ev) =>
{
new Commands.DiffTool(repo, new Models.DiffOption(vm.Base.Head, vm.To.Head, change)).Open();
vm.OpenInExternalDiffTool(change);
ev.Handled = true;
};
menu.Items.Add(openWithMerger);
if (change.Index != Models.ChangeState.Deleted)
{
var full = Path.GetFullPath(Path.Combine(repo, change.Path));
var full = vm.GetAbsPath(change.Path);
var explore = new MenuItem();
explore.Header = App.Text("RevealFile");
explore.Icon = App.CreateMenuIcon("Icons.Explore");
@@ -99,7 +98,7 @@ namespace SourceGit.Views
copyFullPath.Tag = OperatingSystem.IsMacOS() ? "⌘+⇧+C" : "Ctrl+Shift+C";
copyFullPath.Click += async (_, ev) =>
{
await App.CopyTextAsync(Native.OS.GetAbsPath(repo, change.Path));
await App.CopyTextAsync(vm.GetAbsPath(change.Path));
ev.Handled = true;
};
@@ -133,7 +132,7 @@ namespace SourceGit.Views
{
var builder = new StringBuilder();
foreach (var c in selected)
builder.AppendLine(Native.OS.GetAbsPath(repo, c.Path));
builder.AppendLine(vm.GetAbsPath(c.Path));
await App.CopyTextAsync(builder.ToString());
ev.Handled = true;

View File

@@ -257,6 +257,14 @@ namespace SourceGit.Views
ev.Handled = true;
};
var compareWithHead = new MenuItem();
compareWithHead.Header = App.Text("TagCM.CompareWithHead");
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
compareWithHead.Click += (_, _) =>
{
App.ShowWindow(new ViewModels.BranchCompare(repo.FullPath, tag, repo.CurrentBranch));
};
var archive = new MenuItem();
archive.Icon = App.CreateMenuIcon("Icons.Archive");
archive.Header = App.Text("Archive");
@@ -273,6 +281,8 @@ namespace SourceGit.Views
menu.Items.Add(pushTag);
menu.Items.Add(deleteTag);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(compareWithHead);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(archive);
menu.Items.Add(new MenuItem() { Header = "-" });