Skip to content

Commit b2aac68

Browse files
committed
refactor: rewrite integration for git difftool and git mergetool command
Signed-off-by: leo <[email protected]>
1 parent 122de2e commit b2aac68

File tree

9 files changed

+105
-70
lines changed

9 files changed

+105
-70
lines changed

src/Commands/Command.cs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,24 @@ public enum EditorType
3737
public bool RaiseError { get; set; } = true;
3838
public Models.ICommandLog Log { get; set; } = null;
3939

40+
public void Exec()
41+
{
42+
try
43+
{
44+
var start = CreateGitStartInfo(false);
45+
Process.Start(start);
46+
}
47+
catch (Exception ex)
48+
{
49+
App.RaiseException(Context, ex.Message);
50+
}
51+
}
52+
4053
public async Task<bool> ExecAsync()
4154
{
4255
Log?.AppendLine($"$ git {Args}\n");
4356

44-
var start = CreateGitStartInfo();
57+
var start = CreateGitStartInfo(true);
4558
var errs = new List<string>();
4659
var proc = new Process() { StartInfo = start };
4760

@@ -118,7 +131,7 @@ public async Task<bool> ExecAsync()
118131

119132
protected async Task<Result> ReadToEndAsync()
120133
{
121-
var start = CreateGitStartInfo();
134+
var start = CreateGitStartInfo(true);
122135
var proc = new Process() { StartInfo = start };
123136

124137
try
@@ -140,17 +153,21 @@ protected async Task<Result> ReadToEndAsync()
140153
return rs;
141154
}
142155

143-
private ProcessStartInfo CreateGitStartInfo()
156+
private ProcessStartInfo CreateGitStartInfo(bool redirect)
144157
{
145158
var start = new ProcessStartInfo();
146159
start.FileName = Native.OS.GitExecutable;
147160
start.Arguments = "--no-pager -c core.quotepath=off -c credential.helper=manager ";
148161
start.UseShellExecute = false;
149162
start.CreateNoWindow = true;
150-
start.RedirectStandardOutput = true;
151-
start.RedirectStandardError = true;
152-
start.StandardOutputEncoding = Encoding.UTF8;
153-
start.StandardErrorEncoding = Encoding.UTF8;
163+
164+
if (redirect)
165+
{
166+
start.RedirectStandardOutput = true;
167+
start.RedirectStandardError = true;
168+
start.StandardOutputEncoding = Encoding.UTF8;
169+
start.StandardErrorEncoding = Encoding.UTF8;
170+
}
154171

155172
// Force using this app as SSH askpass program
156173
var selfExecFile = Process.GetCurrentProcess().MainModule!.FileName;

src/Commands/DiffTool.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.IO;
2+
3+
namespace SourceGit.Commands
4+
{
5+
public class DiffTool : Command
6+
{
7+
public DiffTool(string repo, int type, string exec, Models.DiffOption option)
8+
{
9+
WorkingDirectory = repo;
10+
Context = repo;
11+
12+
_merger = Models.ExternalMerger.Supported.Find(x => x.Type == type);
13+
_exec = exec;
14+
_option = option;
15+
}
16+
17+
public void Open()
18+
{
19+
if (_merger == null)
20+
{
21+
App.RaiseException(Context, "Invalid merge tool in preference setting!");
22+
return;
23+
}
24+
25+
if (_merger.Type == 0)
26+
{
27+
Args = $"difftool -g --no-prompt {_option}";
28+
}
29+
else if (File.Exists(_exec))
30+
{
31+
Args = $"-c difftool.sourcegit.cmd=\"\\\"{_exec}\\\" {_merger.DiffCmd}\" difftool --tool=sourcegit --no-prompt {_option}";
32+
}
33+
else
34+
{
35+
App.RaiseException(Context, $"Can NOT find external diff tool in '{_exec}'!");
36+
return;
37+
}
38+
39+
Exec();
40+
}
41+
42+
private Models.ExternalMerger _merger;
43+
private string _exec;
44+
private Models.DiffOption _option;
45+
}
46+
}

src/Commands/MergeTool.cs

Lines changed: 23 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,69 +3,45 @@
33

44
namespace SourceGit.Commands
55
{
6-
public static class MergeTool
6+
public class MergeTool : Command
77
{
8-
public static async Task<bool> OpenForMergeAsync(string repo, int toolType, string toolPath, string file)
8+
public MergeTool(string repo, int type, string exec, string file)
99
{
10-
var cmd = new Command();
11-
cmd.WorkingDirectory = repo;
12-
cmd.Context = repo;
13-
cmd.RaiseError = true;
10+
WorkingDirectory = repo;
11+
Context = exec;
1412

15-
// NOTE: If no <file> names are specified, 'git mergetool' will run the merge tool program on every file with merge conflicts.
16-
var fileArg = string.IsNullOrEmpty(file) ? "" : $"\"{file}\"";
17-
18-
if (toolType == 0)
19-
{
20-
cmd.Args = $"mergetool {fileArg}";
21-
return await cmd.ExecAsync().ConfigureAwait(false);
22-
}
13+
_merger = Models.ExternalMerger.Supported.Find(x => x.Type == type);
14+
_exec = exec;
15+
_file = string.IsNullOrEmpty(file) ? "" : $"\"{file}\"";
16+
}
2317

24-
if (!File.Exists(toolPath))
18+
public async Task<bool> OpenAsync()
19+
{
20+
if (_merger == null)
2521
{
26-
App.RaiseException(repo, $"Can NOT find external merge tool in '{toolPath}'!");
22+
App.RaiseException(Context, "Invalid merge tool in preference setting!");
2723
return false;
2824
}
2925

30-
var supported = Models.ExternalMerger.Supported.Find(x => x.Type == toolType);
31-
if (supported == null)
26+
if (_merger.Type == 0)
3227
{
33-
App.RaiseException(repo, "Invalid merge tool in preference setting!");
34-
return false;
28+
Args = $"mergetool {_file}";
3529
}
36-
37-
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit {fileArg}";
38-
return await cmd.ExecAsync().ConfigureAwait(false);
39-
}
40-
41-
public static async Task<bool> OpenForDiffAsync(string repo, int toolType, string toolPath, Models.DiffOption option)
42-
{
43-
var cmd = new Command();
44-
cmd.WorkingDirectory = repo;
45-
cmd.Context = repo;
46-
cmd.RaiseError = true;
47-
48-
if (toolType == 0)
49-
{
50-
cmd.Args = $"difftool -g --no-prompt {option}";
51-
return await cmd.ExecAsync();
52-
}
53-
54-
if (!File.Exists(toolPath))
30+
else if (File.Exists(_exec))
5531
{
56-
App.RaiseException(repo, $"Can NOT find external diff tool in '{toolPath}'!");
57-
return false;
32+
Args = $"-c mergetool.sourcegit.cmd=\"\\\"{_exec}\\\" {_merger.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit {_file}";
5833
}
59-
60-
var supported = Models.ExternalMerger.Supported.Find(x => x.Type == toolType);
61-
if (supported == null)
34+
else
6235
{
63-
App.RaiseException(repo, "Invalid merge tool in preference setting!");
36+
App.RaiseException(Context, $"Can NOT find external merge tool in '{_exec}'!");
6437
return false;
6538
}
6639

67-
cmd.Args = $"-c difftool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.DiffCmd}\" difftool --tool=sourcegit --no-prompt {option}";
68-
return await cmd.ExecAsync().ConfigureAwait(false);
40+
return await ExecAsync().ConfigureAwait(false);
6941
}
42+
43+
private Models.ExternalMerger _merger;
44+
private string _exec;
45+
private string _file;
7046
}
7147
}

src/ViewModels/BranchCompare.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,13 @@ public ContextMenu CreateChangeContextMenu()
125125
var openWithMerger = new MenuItem();
126126
openWithMerger.Header = App.Text("OpenInExternalMergeTool");
127127
openWithMerger.Icon = App.CreateMenuIcon("Icons.OpenWith");
128-
openWithMerger.Click += (sender, ev) =>
128+
openWithMerger.Click += (_, ev) =>
129129
{
130130
var toolType = Preferences.Instance.ExternalMergeToolType;
131131
var toolPath = Preferences.Instance.ExternalMergeToolPath;
132132
var opt = new Models.DiffOption(_based.Head, _to.Head, change);
133133

134-
_ = Commands.MergeTool.OpenForDiffAsync(_repo, toolType, toolPath, opt);
134+
new Commands.DiffTool(_repo, toolType, toolPath, opt).Open();
135135
ev.Handled = true;
136136
};
137137
menu.Items.Add(openWithMerger);

src/ViewModels/CommitDetail.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,13 +325,12 @@ public ContextMenu CreateChangeContextMenu(Models.Change change)
325325
var openWithMerger = new MenuItem();
326326
openWithMerger.Header = App.Text("OpenInExternalMergeTool");
327327
openWithMerger.Icon = App.CreateMenuIcon("Icons.OpenWith");
328-
openWithMerger.Click += (sender, ev) =>
328+
openWithMerger.Click += (_, ev) =>
329329
{
330330
var toolType = Preferences.Instance.ExternalMergeToolType;
331331
var toolPath = Preferences.Instance.ExternalMergeToolPath;
332332
var opt = new Models.DiffOption(_commit, change);
333-
334-
_ = Commands.MergeTool.OpenForDiffAsync(_repo.FullPath, toolType, toolPath, opt);
333+
new Commands.DiffTool(_repo.FullPath, toolType, toolPath, opt).Open();
335334
ev.Handled = true;
336335
};
337336

src/ViewModels/DiffContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public void OpenExternalMergeTool()
9797
{
9898
var toolType = Preferences.Instance.ExternalMergeToolType;
9999
var toolPath = Preferences.Instance.ExternalMergeToolPath;
100-
Task.Run(() => Commands.MergeTool.OpenForDiffAsync(_repo, toolType, toolPath, _option));
100+
new Commands.DiffTool(_repo, toolType, toolPath, _option).Open();
101101
}
102102

103103
private void LoadDiffContent()

src/ViewModels/RevisionCompare.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ public ContextMenu CreateChangeContextMenu()
144144
var opt = new Models.DiffOption(GetSHA(_startPoint), GetSHA(_endPoint), change);
145145
var toolType = Preferences.Instance.ExternalMergeToolType;
146146
var toolPath = Preferences.Instance.ExternalMergeToolPath;
147-
148-
Task.Run(() => Commands.MergeTool.OpenForDiffAsync(_repo, toolType, toolPath, opt));
147+
new Commands.DiffTool(_repo, toolType, toolPath, opt).Open();
149148
ev.Handled = true;
150149
};
151150
menu.Items.Add(openWithMerger);

src/ViewModels/StashesPage.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,7 @@ public ContextMenu MakeContextMenuForChange()
231231
var toolType = Preferences.Instance.ExternalMergeToolType;
232232
var toolPath = Preferences.Instance.ExternalMergeToolPath;
233233
var opt = new Models.DiffOption($"{_selectedStash.SHA}^", _selectedStash.SHA, change);
234-
235-
Task.Run(() => Commands.MergeTool.OpenForDiffAsync(_repo.FullPath, toolType, toolPath, opt));
234+
new Commands.DiffTool(_repo.FullPath, toolType, toolPath, opt).Open();
236235
ev.Handled = true;
237236
};
238237

src/ViewModels/WorkingCopy.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -464,12 +464,12 @@ public async void UseMine(List<Models.Change> changes)
464464
_repo.SetWatcherEnabled(true);
465465
}
466466

467-
public async Task UseExternalMergeTool(Models.Change change)
467+
public async Task<bool> UseExternalMergeTool(Models.Change change)
468468
{
469469
var toolType = Preferences.Instance.ExternalMergeToolType;
470470
var toolPath = Preferences.Instance.ExternalMergeToolPath;
471471
var file = change?.Path;
472-
await Commands.MergeTool.OpenForMergeAsync(_repo.FullPath, toolType, toolPath, file);
472+
return await new Commands.MergeTool(_repo.FullPath, toolType, toolPath, file).OpenAsync();
473473
}
474474

475475
public void ContinueMerge()
@@ -598,7 +598,7 @@ public ContextMenu CreateContextMenuForUnstagedChanges(string selectedSingleFold
598598
var toolType = Preferences.Instance.ExternalMergeToolType;
599599
var toolPath = Preferences.Instance.ExternalMergeToolPath;
600600
var opt = new Models.DiffOption(change, true);
601-
_ = Commands.MergeTool.OpenForDiffAsync(_repo.FullPath, toolType, toolPath, opt);
601+
new Commands.DiffTool(_repo.FullPath, toolType, toolPath, opt).Open();
602602
}
603603

604604
e.Handled = true;
@@ -1250,13 +1250,12 @@ public ContextMenu CreateContextMenuForStagedChanges(string selectedSingleFolder
12501250
var openWithMerger = new MenuItem();
12511251
openWithMerger.Header = App.Text("OpenInExternalMergeTool");
12521252
openWithMerger.Icon = App.CreateMenuIcon("Icons.OpenWith");
1253-
openWithMerger.Click += (sender, ev) =>
1253+
openWithMerger.Click += (_, ev) =>
12541254
{
12551255
var toolType = Preferences.Instance.ExternalMergeToolType;
12561256
var toolPath = Preferences.Instance.ExternalMergeToolPath;
12571257
var opt = new Models.DiffOption(change, false);
1258-
1259-
_ = Commands.MergeTool.OpenForDiffAsync(_repo.FullPath, toolType, toolPath, opt);
1258+
new Commands.DiffTool(_repo.FullPath, toolType, toolPath, opt).Open();
12601259
ev.Handled = true;
12611260
};
12621261

0 commit comments

Comments
 (0)