Skip to content

Commit 62bdadc

Browse files
committed
code_review: PR #2043
- Opening repo as folder in VS should always be available - Use single `_optionsGenerator` instead of `_execArgsGenerator` and `_subOptionsFinder` - Make sure path is always quoted Signed-off-by: leo <[email protected]>
1 parent 3dbab1c commit 62bdadc

File tree

8 files changed

+76
-60
lines changed

8 files changed

+76
-60
lines changed

src/Models/ExternalTool.cs

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,28 @@ namespace SourceGit.Models
1212
{
1313
public class ExternalTool
1414
{
15+
public class LaunchOption
16+
{
17+
public string Title { get; set; }
18+
public string Args { get; set; }
19+
20+
public LaunchOption(string title, string args)
21+
{
22+
Title = title;
23+
Args = args;
24+
}
25+
}
26+
1527
public string Name { get; }
1628
public string ExecFile { get; }
1729
public Bitmap IconImage { get; }
1830

19-
public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null, Func<string, List<string>> subOptionsFinder = null)
31+
public ExternalTool(string name, string icon, string execFile, Func<string, List<LaunchOption>> optionsGenerator = null)
2032
{
2133
Name = name;
2234
ExecFile = execFile;
23-
_execArgsGenerator = execArgsGenerator ?? (path => path.Quoted());
24-
_subOptionsFinder = subOptionsFinder;
35+
36+
_optionsGenerator = optionsGenerator;
2537

2638
try
2739
{
@@ -35,30 +47,25 @@ public ExternalTool(string name, string icon, string execFile, Func<string, stri
3547
}
3648
}
3749

38-
public void Open(string path)
50+
public List<LaunchOption> MakeLaunchOptions(string repo)
3951
{
40-
// The executable file may be removed after the tool list is loaded (once time on startup).
41-
if (!File.Exists(ExecFile))
42-
return;
43-
44-
Process.Start(new ProcessStartInfo()
45-
{
46-
FileName = ExecFile,
47-
Arguments = _execArgsGenerator.Invoke(path),
48-
UseShellExecute = false,
49-
});
52+
return _optionsGenerator?.Invoke(repo);
5053
}
5154

52-
public List<string> FindSubOptions(string path)
55+
public void Launch(string args)
5356
{
54-
if (_subOptionsFinder == null)
55-
return null;
56-
57-
return _subOptionsFinder.Invoke(path);
57+
if (File.Exists(ExecFile))
58+
{
59+
Process.Start(new ProcessStartInfo()
60+
{
61+
FileName = ExecFile,
62+
Arguments = args,
63+
UseShellExecute = false,
64+
});
65+
}
5866
}
5967

60-
private Func<string, string> _execArgsGenerator = null;
61-
private Func<string, List<string>> _subOptionsFinder = null;
68+
private Func<string, List<LaunchOption>> _optionsGenerator = null;
6269
}
6370

6471
public class VisualStudioInstance
@@ -140,20 +147,20 @@ public ExternalToolsFinder()
140147
_customization ??= new ExternalToolCustomization();
141148
}
142149

143-
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null, Func<string, List<string>> subOptionsFinder = null)
150+
public void TryAdd(string name, string icon, Func<string> finder, Func<string, List<ExternalTool.LaunchOption>> optionsGenerator = null)
144151
{
145152
if (_customization.Excludes.Contains(name))
146153
return;
147154

148155
if (_customization.Tools.TryGetValue(name, out var customPath) && File.Exists(customPath))
149156
{
150-
Tools.Add(new ExternalTool(name, icon, customPath, execArgsGenerator, subOptionsFinder));
157+
Tools.Add(new ExternalTool(name, icon, customPath, optionsGenerator));
151158
}
152159
else
153160
{
154161
var path = finder();
155162
if (!string.IsNullOrEmpty(path) && File.Exists(path))
156-
Tools.Add(new ExternalTool(name, icon, path, execArgsGenerator, subOptionsFinder));
163+
Tools.Add(new ExternalTool(name, icon, path, optionsGenerator));
157164
}
158165
}
159166

src/Native/Windows.cs

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ private void FindVisualStudio(Models.ExternalToolsFinder finder)
401401
{
402402
var exec = instance.ProductPath;
403403
var icon = instance.IsPrerelease ? "vs-preview" : "vs";
404-
finder.TryAdd(instance.DisplayName, icon, () => exec, GenerateCommandlineArgsForVisualStudio, FindVisualStudioSolutions);
404+
finder.TryAdd(instance.DisplayName, icon, () => exec, GenerateVSProjectLaunchOptions);
405405
}
406406
}
407407
}
@@ -444,35 +444,34 @@ private void OpenFolderAndSelectFile(string folderPath)
444444
}
445445
}
446446

447-
private string GenerateCommandlineArgsForVisualStudio(string path)
447+
private List<Models.ExternalTool.LaunchOption> GenerateVSProjectLaunchOptions(string path)
448448
{
449-
var solutions = FindVisualStudioSolutions(path);
450-
return solutions.Count > 0 ? solutions[0].Quoted() : path.Quoted();
451-
}
452-
453-
public List<string> FindVisualStudioSolutions(string path)
454-
{
455-
var solutions = new List<string>();
456-
if (!Directory.Exists(path))
457-
return solutions;
458-
459-
void Search(DirectoryInfo dir, int depth)
449+
if (Directory.Exists(path))
460450
{
461-
if (depth < 0)
462-
return;
451+
void Search(List<Models.ExternalTool.LaunchOption> opts, DirectoryInfo dir, string root, int depth)
452+
{
453+
if (depth < 0)
454+
return;
463455

464-
foreach (var file in dir.GetFiles("*.sln"))
465-
solutions.Add(file.FullName);
456+
foreach (var file in dir.GetFiles())
457+
{
458+
if (file.Name.EndsWith(".sln", StringComparison.OrdinalIgnoreCase) ||
459+
file.Name.EndsWith(".slnx", StringComparison.OrdinalIgnoreCase))
460+
opts.Add(new(Path.GetRelativePath(root, file.FullName), file.FullName.Quoted()));
461+
}
466462

467-
foreach (var file in dir.GetFiles("*.slnx"))
468-
solutions.Add(file.FullName);
463+
foreach (var subDir in dir.GetDirectories())
464+
Search(opts, subDir, root, depth - 1);
465+
}
469466

470-
foreach (var subDir in dir.GetDirectories())
471-
Search(subDir, depth - 1);
467+
var rootDir = new DirectoryInfo(path);
468+
var options = new List<Models.ExternalTool.LaunchOption>();
469+
Search(options, rootDir, rootDir.FullName, 4);
470+
if (options.Count > 0)
471+
return options;
472472
}
473-
Search(new DirectoryInfo(path), 4);
474473

475-
return solutions;
474+
return null;
476475
}
477476
}
478477
}

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@
729729
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
730730
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">CLEAR NOTIFICATIONS</x:String>
731731
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">Only highlight current branch</x:String>
732+
<x:String x:Key="Text.Repository.OpenAsFolder" xml:space="preserve">Open as Folder</x:String>
732733
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open in {0}</x:String>
733734
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open in External Tools</x:String>
734735
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@
733733
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String>
734734
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">清空通知列表</x:String>
735735
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">仅高亮显示当前分支</x:String>
736+
<x:String x:Key="Text.Repository.OpenAsFolder" xml:space="preserve">本仓库(文件夹)</x:String>
736737
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">在 {0} 中打开</x:String>
737738
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">使用外部工具打开</x:String>
738739
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">远程列表</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@
733733
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新增分支</x:String>
734734
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">清除所有通知</x:String>
735735
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">路線圖中僅對目前分支上色</x:String>
736+
<x:String x:Key="Text.Repository.OpenAsFolder" xml:space="preserve">此存放庫(資料夾)</x:String>
736737
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">在 {0} 中開啟</x:String>
737738
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">使用外部工具開啟</x:String>
738739
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">遠端列表</x:String>

src/ViewModels/CommitDetail.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ await Commands.SaveRevisionFile
343343
if (tool == null)
344344
Native.OS.OpenWithDefaultEditor(tmpFile);
345345
else
346-
tool.Open(tmpFile);
346+
tool.Launch(tmpFile.Quoted());
347347
}
348348

349349
public async Task SaveRevisionFileAsync(Models.Object file, string saveTo)

src/Views/RepositoryToolbar.axaml.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using System.IO;
32

43
using Avalonia.Controls;
54
using Avalonia.Input;
@@ -63,34 +62,42 @@ private void OpenWithExternalTools(object sender, RoutedEventArgs ev)
6362
item.Header = App.Text("Repository.OpenIn", dupTool.Name);
6463
item.Icon = new Image { Width = 16, Height = 16, Source = dupTool.IconImage };
6564

66-
var subOptions = dupTool.FindSubOptions(fullpath);
67-
if (subOptions != null && subOptions.Count > 1)
65+
var options = dupTool.MakeLaunchOptions(fullpath);
66+
if (options is { Count: > 0 })
6867
{
69-
foreach (var subOption in subOptions)
68+
var openAsFolder = new MenuItem();
69+
openAsFolder.Header = App.Text("Repository.OpenAsFolder");
70+
openAsFolder.Click += (_, e) =>
71+
{
72+
dupTool.Launch(fullpath.Quoted());
73+
e.Handled = true;
74+
};
75+
item.Items.Add(openAsFolder);
76+
item.Items.Add(new MenuItem() { Header = "-" });
77+
78+
foreach (var opt in options)
7079
{
7180
var subItem = new MenuItem();
72-
subItem.Header = Path.GetFileName(subOption);
81+
subItem.Header = opt.Title;
7382
subItem.Click += (_, e) =>
7483
{
75-
dupTool.Open(subOption);
84+
dupTool.Launch(opt.Args);
7685
e.Handled = true;
7786
};
7887

7988
item.Items.Add(subItem);
8089
}
81-
82-
menu.Items.Add(item);
8390
}
8491
else
8592
{
8693
item.Click += (_, e) =>
8794
{
88-
dupTool.Open(fullpath);
95+
dupTool.Launch(fullpath.Quoted());
8996
e.Handled = true;
9097
};
91-
92-
menu.Items.Add(item);
9398
}
99+
100+
menu.Items.Add(item);
94101
}
95102
}
96103

src/Views/WorkingCopy.axaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1290,7 +1290,7 @@ private void TryAddOpenFileToContextMenu(ContextMenu menu, string fullpath)
12901290
item.Icon = new Image { Width = 16, Height = 16, Source = tool.IconImage };
12911291
item.Click += (_, e) =>
12921292
{
1293-
tool.Open(fullpath);
1293+
tool.Launch(fullpath.Quoted());
12941294
e.Handled = true;
12951295
};
12961296

0 commit comments

Comments
 (0)