Skip to content

Commit 47824dc

Browse files
authored
Add button for running external mergetool on ALL conflicts (#1173)
* Make a few non-translated strings localizable (in Conflict view) * Add button and wiring to run mergetool on all conflicts * Corrected spelling and wording in related code and exception msg
1 parent 3b18ee0 commit 47824dc

File tree

7 files changed

+48
-25
lines changed

7 files changed

+48
-25
lines changed

src/Commands/MergeTool.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ public static bool OpenForMerge(string repo, int toolType, string toolPath, stri
1313
cmd.Context = repo;
1414
cmd.RaiseError = true;
1515

16+
// NOTE: If no <file> names are specified, 'git mergetool' will run the merge tool program on every file with merge conflicts.
17+
var file_arg = string.IsNullOrEmpty(file) ? "" : $"\"{file}\"";
18+
1619
if (toolType == 0)
1720
{
18-
cmd.Args = $"mergetool \"{file}\"";
21+
cmd.Args = $"mergetool {file_arg}";
1922
return cmd.Exec();
2023
}
2124

@@ -32,7 +35,7 @@ public static bool OpenForMerge(string repo, int toolType, string toolPath, stri
3235
return false;
3336
}
3437

35-
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit \"{file}\"";
38+
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit {file_arg}";
3639
return cmd.Exec();
3740
}
3841

src/Models/Change.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class Change
3636
public string OriginalPath { get; set; } = "";
3737
public ChangeDataForAmend DataForAmend { get; set; } = null;
3838

39-
public bool IsConflit
39+
public bool IsConflict
4040
{
4141
get
4242
{

src/Resources/Locales/en_US.axaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,11 @@
726726
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Stage all changes and commit</x:String>
727727
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithFilter">You have staged {0} file(s) but only {1} file(s) displayed ({2} files are filtered out). Do you want to continue?</x:String>
728728
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLICTS DETECTED</x:String>
729+
<x:String x:Key="Text.WorkingCopy.Conflicts.OpenExternalMergeTool" xml:space="preserve">OPEN EXTERNAL MERGETOOL</x:String>
730+
<x:String x:Key="Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts" xml:space="preserve">OPEN ALL CONFLICTS IN EXTERNAL MERGETOOL</x:String>
729731
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">FILE CONFLICTS ARE RESOLVED</x:String>
732+
<x:String x:Key="Text.WorkingCopy.Conflicts.UseMine" xml:space="preserve">USE MINE</x:String>
733+
<x:String x:Key="Text.WorkingCopy.Conflicts.UseTheirs" xml:space="preserve">USE THEIRS</x:String>
730734
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUDE UNTRACKED FILES</x:String>
731735
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NO RECENT INPUT MESSAGES</x:String>
732736
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NO COMMIT TEMPLATES</x:String>

src/ViewModels/WorkingCopy.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ public void SetData(List<Models.Change> changes)
243243
// Just force refresh selected changes.
244244
Dispatcher.UIThread.Invoke(() =>
245245
{
246-
HasUnsolvedConflicts = _cached.Find(x => x.IsConflit) != null;
246+
HasUnsolvedConflicts = _cached.Find(x => x.IsConflict) != null;
247247

248248
UpdateDetail();
249249
UpdateInProgressState();
@@ -275,7 +275,7 @@ public void SetData(List<Models.Change> changes)
275275
if (c.WorkTree != Models.ChangeState.None)
276276
{
277277
unstaged.Add(c);
278-
hasConflict |= c.IsConflit;
278+
hasConflict |= c.IsConflict;
279279
}
280280
}
281281

@@ -314,6 +314,12 @@ public void SetData(List<Models.Change> changes)
314314
});
315315
}
316316

317+
public void OpenExternalMergeToolAllConflicts()
318+
{
319+
// No <file> arg, mergetool runs on all files with merge conflicts!
320+
UseExternalMergeTool(null);
321+
}
322+
317323
public void OpenAssumeUnchanged()
318324
{
319325
App.OpenDialog(new Views.AssumeUnchangedManager()
@@ -373,7 +379,7 @@ public async void UseTheirs(List<Models.Change> changes)
373379

374380
foreach (var change in changes)
375381
{
376-
if (!change.IsConflit)
382+
if (!change.IsConflict)
377383
continue;
378384

379385
if (change.WorkTree == Models.ChangeState.Deleted)
@@ -413,7 +419,7 @@ public async void UseMine(List<Models.Change> changes)
413419

414420
foreach (var change in changes)
415421
{
416-
if (!change.IsConflit)
422+
if (!change.IsConflict)
417423
continue;
418424

419425
if (change.Index == Models.ChangeState.Deleted)
@@ -448,7 +454,8 @@ public async void UseExternalMergeTool(Models.Change change)
448454
{
449455
var toolType = Preferences.Instance.ExternalMergeToolType;
450456
var toolPath = Preferences.Instance.ExternalMergeToolPath;
451-
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, toolType, toolPath, change.Path));
457+
var file = change?.Path; // NOTE: With no <file> arg, mergetool runs on on every file with merge conflicts!
458+
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, toolType, toolPath, file));
452459
}
453460

454461
public void ContinueMerge()
@@ -585,7 +592,7 @@ public ContextMenu CreateContextMenuForUnstagedChanges()
585592
menu.Items.Add(openWith);
586593
menu.Items.Add(new MenuItem() { Header = "-" });
587594

588-
if (change.IsConflit)
595+
if (change.IsConflict)
589596
{
590597
var useTheirs = new MenuItem();
591598
useTheirs.Icon = App.CreateMenuIcon("Icons.Incoming");
@@ -924,20 +931,20 @@ public ContextMenu CreateContextMenuForUnstagedChanges()
924931
else
925932
{
926933
var hasConflicts = false;
927-
var hasNoneConflicts = false;
934+
var hasNonConflicts = false;
928935
foreach (var change in _selectedUnstaged)
929936
{
930-
if (change.IsConflit)
937+
if (change.IsConflict)
931938
hasConflicts = true;
932939
else
933-
hasNoneConflicts = true;
940+
hasNonConflicts = true;
934941
}
935942

936943
if (hasConflicts)
937944
{
938-
if (hasNoneConflicts)
945+
if (hasNonConflicts)
939946
{
940-
App.RaiseException(_repo.FullPath, "You have selected both non-conflict changes with conflicts!");
947+
App.RaiseException(_repo.FullPath, "Selection contains both conflict and non-conflict changes!");
941948
return null;
942949
}
943950

@@ -1644,7 +1651,7 @@ private void SetDetail(Models.Change change, bool isUnstaged)
16441651

16451652
if (change == null)
16461653
DetailContext = null;
1647-
else if (change.IsConflit && isUnstaged)
1654+
else if (change.IsConflict && isUnstaged)
16481655
DetailContext = new Conflict(_repo, this, change);
16491656
else
16501657
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);

src/Views/ChangeStatusIcon.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public override void Render(DrawingContext context)
9393
string indicator;
9494
if (IsUnstagedChange)
9595
{
96-
if (Change.IsConflit)
96+
if (Change.IsConflict)
9797
{
9898
background = Brushes.OrangeRed;
9999
indicator = "!";
@@ -139,7 +139,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
139139
}
140140

141141
if (isUnstaged)
142-
ToolTip.SetTip(this, c.IsConflit ? "Conflict" : TIPS[(int)c.WorkTree]);
142+
ToolTip.SetTip(this, c.IsConflict ? "Conflict" : TIPS[(int)c.WorkTree]);
143143
else
144144
ToolTip.SetTip(this, TIPS[(int)c.Index]);
145145

src/Views/Conflict.axaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@
105105
</Border>
106106

107107
<StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
108-
<Button Classes="flat" Content="USE THEIRS" Command="{Binding UseTheirs}"/>
109-
<Button Classes="flat" Margin="8,0,0,0" Content="USE MINE" Command="{Binding UseMine}"/>
110-
<Button Classes="flat" Margin="8,0,0,0" Content="OPEN EXTERNAL MERGETOOL" Command="{Binding OpenExternalMergeTool}"/>
108+
<Button Classes="flat" Margin="0,0,0,0" Content="{DynamicResource Text.WorkingCopy.Conflicts.UseTheirs}" Command="{Binding UseTheirs}"/>
109+
<Button Classes="flat" Margin="8,0,0,0" Content="{DynamicResource Text.WorkingCopy.Conflicts.UseMine}" Command="{Binding UseMine}"/>
110+
<Button Classes="flat" Margin="8,0,0,0" Content="{DynamicResource Text.WorkingCopy.Conflicts.OpenExternalMergeTool}" Command="{Binding OpenExternalMergeTool}"/>
111111
</StackPanel>
112112
</StackPanel>
113113

src/Views/WorkingCopy.axaml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,26 +61,35 @@
6161
<Grid Grid.Row="1" RowDefinitions="28,*">
6262
<!-- Unstaged Toolbar -->
6363
<Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}">
64-
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto,Auto">
64+
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto,Auto,Auto">
6565
<Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/>
6666
<TextBlock Grid.Column="1" Text="{DynamicResource Text.WorkingCopy.Unstaged}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0"/>
6767
<TextBlock Grid.Column="2" FontWeight="Bold" Foreground="{DynamicResource Brush.FG2}" Text="{Binding Unstaged, Converter={x:Static c:ListConverters.ToCount}}"/>
6868
<v:LoadingIcon Grid.Column="3" Width="14" Height="14" Margin="8,0,0,0" IsVisible="{Binding IsStaging}"/>
6969

7070
<Button Grid.Column="5"
71+
Classes="icon_button"
72+
Width="26" Height="14"
73+
Padding="0"
74+
IsVisible="{Binding HasUnsolvedConflicts}"
75+
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts}"
76+
Command="{Binding OpenExternalMergeToolAllConflicts}">
77+
<Path Width="14" Height="14" Data="{StaticResource Icons.Conflict}"/>
78+
</Button>
79+
<Button Grid.Column="6"
7180
Classes="icon_button"
7281
Width="26" Height="14"
7382
Padding="0"
7483
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.ViewAssumeUnchaged}"
7584
Command="{Binding OpenAssumeUnchanged}">
7685
<Path Width="14" Height="14" Data="{StaticResource Icons.File.Ignore}"/>
7786
</Button>
78-
<ToggleButton Grid.Column="6"
87+
<ToggleButton Grid.Column="7"
7988
Classes="toggle_untracked"
8089
Width="26" Height="14"
8190
ToolTip.Tip="{DynamicResource Text.WorkingCopy.IncludeUntracked}"
8291
IsChecked="{Binding IncludeUntracked, Mode=TwoWay}"/>
83-
<Button Grid.Column="7"
92+
<Button Grid.Column="8"
8493
Classes="icon_button"
8594
Width="26" Height="14"
8695
Padding="0"
@@ -93,15 +102,15 @@
93102
</ToolTip.Tip>
94103
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
95104
</Button>
96-
<Button Grid.Column="8"
105+
<Button Grid.Column="9"
97106
Classes="icon_button"
98107
Width="26" Height="14"
99108
Padding="0"
100109
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.StageAll}"
101110
Command="{Binding StageAll}">
102111
<Path Width="14" Height="14" Data="{StaticResource Icons.DoubleDown}"/>
103112
</Button>
104-
<v:ChangeViewModeSwitcher Grid.Column="9"
113+
<v:ChangeViewModeSwitcher Grid.Column="10"
105114
Width="26" Height="14"
106115
Margin="0,1,0,0"
107116
ViewMode="{Binding Source={x:Static vm:Preferences.Instance}, Path=UnstagedChangeViewMode, Mode=TwoWay}"/>

0 commit comments

Comments
 (0)