refactor: use a new Models.ChangeState.Conflicted to represent all the unmerged file state (#1359)

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-05-24 20:25:05 +08:00
parent 30d4c1008a
commit ef53dd0025
No known key found for this signature in database
6 changed files with 87 additions and 135 deletions

View file

@ -128,30 +128,16 @@ namespace SourceGit.Commands
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Copied); change.Set(Models.ChangeState.Deleted, Models.ChangeState.Copied);
break; break;
case "DD": case "DD":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Deleted);
break;
case "AU": case "AU":
change.Set(Models.ChangeState.Added, Models.ChangeState.Unmerged);
break;
case "UD": case "UD":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Deleted);
break;
case "UA": case "UA":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Added);
break;
case "DU": case "DU":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Unmerged);
break;
case "AA": case "AA":
change.Set(Models.ChangeState.Added, Models.ChangeState.Added);
break;
case "UU": case "UU":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Unmerged); change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
break; break;
case "??": case "??":
change.Set(Models.ChangeState.Untracked, Models.ChangeState.Untracked); change.Set(Models.ChangeState.None, Models.ChangeState.Untracked);
break;
default:
break; break;
} }

View file

@ -6,7 +6,7 @@ namespace SourceGit.Commands
{ {
public partial class QueryStagedChangesWithAmend : Command public partial class QueryStagedChangesWithAmend : Command
{ {
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ACDMTUX])\d{0,6}\t(.*)$")] [GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ACDMT])\d{0,6}\t(.*)$")]
private static partial Regex REG_FORMAT1(); private static partial Regex REG_FORMAT1();
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} R\d{0,6}\t(.*\t.*)$")] [GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} R\d{0,6}\t(.*\t.*)$")]
private static partial Regex REG_FORMAT2(); private static partial Regex REG_FORMAT2();
@ -22,8 +22,9 @@ namespace SourceGit.Commands
public List<Models.Change> Result() public List<Models.Change> Result()
{ {
var rs = ReadToEnd(); var rs = ReadToEnd();
if (rs.IsSuccess) if (!rs.IsSuccess)
{ return [];
var changes = new List<Models.Change>(); var changes = new List<Models.Change>();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines) foreach (var line in lines)
@ -78,9 +79,6 @@ namespace SourceGit.Commands
case "T": case "T":
change.Set(Models.ChangeState.TypeChanged); change.Set(Models.ChangeState.TypeChanged);
break; break;
case "U":
change.Set(Models.ChangeState.Unmerged);
break;
} }
changes.Add(change); changes.Add(change);
} }
@ -89,9 +87,6 @@ namespace SourceGit.Commands
return changes; return changes;
} }
return []; private readonly string _parent;
}
private string _parent = string.Empty;
} }
} }

View file

@ -18,8 +18,8 @@ namespace SourceGit.Models
Deleted, Deleted,
Renamed, Renamed,
Copied, Copied,
Unmerged, Untracked,
Untracked Conflicted,
} }
public class ChangeDataForAmend public class ChangeDataForAmend
@ -36,20 +36,7 @@ namespace SourceGit.Models
public string Path { get; set; } = ""; public string Path { get; set; } = "";
public string OriginalPath { get; set; } = ""; public string OriginalPath { get; set; } = "";
public ChangeDataForAmend DataForAmend { get; set; } = null; public ChangeDataForAmend DataForAmend { get; set; } = null;
public bool IsConflicted => WorkTree == ChangeState.Conflicted;
public bool IsConflict
{
get
{
if (Index == ChangeState.Unmerged || WorkTree == ChangeState.Unmerged)
return true;
if (Index == ChangeState.Added && WorkTree == ChangeState.Added)
return true;
if (Index == ChangeState.Deleted && WorkTree == ChangeState.Deleted)
return true;
return false;
}
}
public void Set(ChangeState index, ChangeState workTree = ChangeState.None) public void Set(ChangeState index, ChangeState workTree = ChangeState.None)
{ {
@ -77,6 +64,7 @@ namespace SourceGit.Models
if (Path[0] == '"') if (Path[0] == '"')
Path = Path.Substring(1, Path.Length - 2); Path = Path.Substring(1, Path.Length - 2);
if (!string.IsNullOrEmpty(OriginalPath) && OriginalPath[0] == '"') if (!string.IsNullOrEmpty(OriginalPath) && OriginalPath[0] == '"')
OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2); OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2);
} }

View file

@ -49,7 +49,6 @@ namespace SourceGit.ViewModels
_change = change; _change = change;
var isSubmodule = repo.Submodules.Find(x => x.Path.Equals(change.Path, StringComparison.Ordinal)) != null; var isSubmodule = repo.Submodules.Find(x => x.Path.Equals(change.Path, StringComparison.Ordinal)) != null;
IsResolved = !isSubmodule && new Commands.IsConflictResolved(repo.FullPath, change).Result(); IsResolved = !isSubmodule && new Commands.IsConflictResolved(repo.FullPath, change).Result();
var context = wc.InProgressContext; var context = wc.InProgressContext;

View file

@ -244,7 +244,7 @@ namespace SourceGit.ViewModels
// Just force refresh selected changes. // Just force refresh selected changes.
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
HasUnsolvedConflicts = _cached.Find(x => x.IsConflict) != null; HasUnsolvedConflicts = _cached.Find(x => x.IsConflicted) != null;
UpdateDetail(); UpdateDetail();
UpdateInProgressState(); UpdateInProgressState();
@ -276,7 +276,7 @@ namespace SourceGit.ViewModels
if (c.WorkTree != Models.ChangeState.None) if (c.WorkTree != Models.ChangeState.None)
{ {
unstaged.Add(c); unstaged.Add(c);
hasConflict |= c.IsConflict; hasConflict |= c.IsConflicted;
} }
} }
@ -378,7 +378,7 @@ namespace SourceGit.ViewModels
foreach (var change in changes) foreach (var change in changes)
{ {
if (!change.IsConflict) if (!change.IsConflicted)
continue; continue;
if (change.WorkTree == Models.ChangeState.Deleted) if (change.WorkTree == Models.ChangeState.Deleted)
@ -420,7 +420,7 @@ namespace SourceGit.ViewModels
foreach (var change in changes) foreach (var change in changes)
{ {
if (!change.IsConflict) if (!change.IsConflicted)
continue; continue;
if (change.Index == Models.ChangeState.Deleted) if (change.Index == Models.ChangeState.Deleted)
@ -547,17 +547,17 @@ namespace SourceGit.ViewModels
public void Commit() public void Commit()
{ {
DoCommit(false, false, false); DoCommit(false, false);
} }
public void CommitWithAutoStage() public void CommitWithAutoStage()
{ {
DoCommit(true, false, false); DoCommit(true, false);
} }
public void CommitWithPush() public void CommitWithPush()
{ {
DoCommit(false, true, false); DoCommit(false, true);
} }
public ContextMenu CreateContextMenuForUnstagedChanges() public ContextMenu CreateContextMenuForUnstagedChanges()
@ -594,7 +594,7 @@ namespace SourceGit.ViewModels
menu.Items.Add(openWith); menu.Items.Add(openWith);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
if (change.IsConflict) if (change.IsConflicted)
{ {
var useTheirs = new MenuItem(); var useTheirs = new MenuItem();
useTheirs.Icon = App.CreateMenuIcon("Icons.Incoming"); useTheirs.Icon = App.CreateMenuIcon("Icons.Incoming");
@ -949,7 +949,7 @@ namespace SourceGit.ViewModels
var hasNonConflicts = false; var hasNonConflicts = false;
foreach (var change in _selectedUnstaged) foreach (var change in _selectedUnstaged)
{ {
if (change.IsConflict) if (change.IsConflicted)
hasConflicts = true; hasConflicts = true;
else else
hasNonConflicts = true; hasNonConflicts = true;
@ -1534,9 +1534,7 @@ namespace SourceGit.ViewModels
var rs = new List<Models.Change>(); var rs = new List<Models.Change>();
foreach (var c in _cached) foreach (var c in _cached)
{ {
if (c.Index != Models.ChangeState.None && if (c.Index != Models.ChangeState.None)
c.Index != Models.ChangeState.Untracked &&
!c.IsConflict)
rs.Add(c); rs.Add(c);
} }
return rs; return rs;
@ -1682,7 +1680,7 @@ namespace SourceGit.ViewModels
if (change == null) if (change == null)
DetailContext = null; DetailContext = null;
else if (change.IsConflict && isUnstaged) else if (change.IsConflicted)
DetailContext = new Conflict(_repo, this, change); DetailContext = new Conflict(_repo, this, change);
else else
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext); DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);
@ -1765,13 +1763,16 @@ namespace SourceGit.ViewModels
if (old.Count != cur.Count) if (old.Count != cur.Count)
return true; return true;
var oldSet = new HashSet<string>(); var oldMap = new Dictionary<string, Models.Change>();
foreach (var c in old) foreach (var c in old)
oldSet.Add($"{c.Path}\n{c.WorkTree}\n{c.Index}"); oldMap.Add(c.Path, c);
foreach (var c in cur) foreach (var c in cur)
{ {
if (!oldSet.Contains($"{c.Path}\n{c.WorkTree}\n{c.Index}")) if (!oldMap.TryGetValue(c.Path, out var o))
return true;
if (o.Index != c.Index || o.WorkTree != c.WorkTree)
return true; return true;
} }

View file

@ -48,25 +48,16 @@ namespace SourceGit.Views
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative), EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
}, },
new LinearGradientBrush new LinearGradientBrush
{
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(238, 160, 14), 0), new GradientStop(Color.FromRgb(228, 172, 67), 1) },
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
},
new LinearGradientBrush
{ {
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(47, 185, 47), 0), new GradientStop(Color.FromRgb(75, 189, 75), 1) }, GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(47, 185, 47), 0), new GradientStop(Color.FromRgb(75, 189, 75), 1) },
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative), EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
}, },
Brushes.OrangeRed,
]; ];
private static readonly string[] INDICATOR = ["?", "±", "T", "+", "", "➜", "❏", "U", "★"]; private static readonly string[] INDICATOR = ["?", "±", "T", "+", "", "➜", "❏", "★", "!"];
private static readonly string[] TIPS = ["Unknown", "Modified", "Type Changed", "Added", "Deleted", "Renamed", "Copied", "Unmerged", "Untracked"]; private static readonly string[] TIPS = ["Unknown", "Modified", "Type Changed", "Added", "Deleted", "Renamed", "Copied", "Untracked", "Conflict"];
private static readonly IBrush BACKGROUND_CONFLICT = Brushes.OrangeRed;
private const string INDICATOR_CONFLICT = "!";
private const string TIP_CONFLICT = "Conflict";
public static readonly StyledProperty<bool> IsUnstagedChangeProperty = public static readonly StyledProperty<bool> IsUnstagedChangeProperty =
AvaloniaProperty.Register<ChangeStatusIcon, bool>(nameof(IsUnstagedChange)); AvaloniaProperty.Register<ChangeStatusIcon, bool>(nameof(IsUnstagedChange));
@ -96,18 +87,10 @@ namespace SourceGit.Views
IBrush background; IBrush background;
string indicator; string indicator;
if (IsUnstagedChange) if (IsUnstagedChange)
{
if (Change.IsConflict)
{
background = BACKGROUND_CONFLICT;
indicator = INDICATOR_CONFLICT;
}
else
{ {
background = BACKGROUNDS[(int)Change.WorkTree]; background = BACKGROUNDS[(int)Change.WorkTree];
indicator = INDICATOR[(int)Change.WorkTree]; indicator = INDICATOR[(int)Change.WorkTree];
} }
}
else else
{ {
background = BACKGROUNDS[(int)Change.Index]; background = BACKGROUNDS[(int)Change.Index];
@ -143,7 +126,7 @@ namespace SourceGit.Views
} }
if (isUnstaged) if (isUnstaged)
ToolTip.SetTip(this, c.IsConflict ? TIP_CONFLICT : TIPS[(int)c.WorkTree]); ToolTip.SetTip(this, TIPS[(int)c.WorkTree]);
else else
ToolTip.SetTip(this, TIPS[(int)c.Index]); ToolTip.SetTip(this, TIPS[(int)c.Index]);