mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-22 05:40:43 +08:00
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 <longshuang@msn.cn>
This commit is contained in:
@@ -12,16 +12,28 @@ namespace SourceGit.Models
|
||||
{
|
||||
public class ExternalTool
|
||||
{
|
||||
public class LaunchOption
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Args { get; set; }
|
||||
|
||||
public LaunchOption(string title, string args)
|
||||
{
|
||||
Title = title;
|
||||
Args = args;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public string ExecFile { get; }
|
||||
public Bitmap IconImage { get; }
|
||||
|
||||
public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null, Func<string, List<string>> subOptionsFinder = null)
|
||||
public ExternalTool(string name, string icon, string execFile, Func<string, List<LaunchOption>> optionsGenerator = null)
|
||||
{
|
||||
Name = name;
|
||||
ExecFile = execFile;
|
||||
_execArgsGenerator = execArgsGenerator ?? (path => path.Quoted());
|
||||
_subOptionsFinder = subOptionsFinder;
|
||||
|
||||
_optionsGenerator = optionsGenerator;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -35,30 +47,25 @@ namespace SourceGit.Models
|
||||
}
|
||||
}
|
||||
|
||||
public void Open(string path)
|
||||
public List<LaunchOption> MakeLaunchOptions(string repo)
|
||||
{
|
||||
// The executable file may be removed after the tool list is loaded (once time on startup).
|
||||
if (!File.Exists(ExecFile))
|
||||
return;
|
||||
return _optionsGenerator?.Invoke(repo);
|
||||
}
|
||||
|
||||
Process.Start(new ProcessStartInfo()
|
||||
public void Launch(string args)
|
||||
{
|
||||
if (File.Exists(ExecFile))
|
||||
{
|
||||
FileName = ExecFile,
|
||||
Arguments = _execArgsGenerator.Invoke(path),
|
||||
UseShellExecute = false,
|
||||
});
|
||||
Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
FileName = ExecFile,
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> FindSubOptions(string path)
|
||||
{
|
||||
if (_subOptionsFinder == null)
|
||||
return null;
|
||||
|
||||
return _subOptionsFinder.Invoke(path);
|
||||
}
|
||||
|
||||
private Func<string, string> _execArgsGenerator = null;
|
||||
private Func<string, List<string>> _subOptionsFinder = null;
|
||||
private Func<string, List<LaunchOption>> _optionsGenerator = null;
|
||||
}
|
||||
|
||||
public class VisualStudioInstance
|
||||
@@ -140,20 +147,20 @@ namespace SourceGit.Models
|
||||
_customization ??= new ExternalToolCustomization();
|
||||
}
|
||||
|
||||
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null, Func<string, List<string>> subOptionsFinder = null)
|
||||
public void TryAdd(string name, string icon, Func<string> finder, Func<string, List<ExternalTool.LaunchOption>> optionsGenerator = null)
|
||||
{
|
||||
if (_customization.Excludes.Contains(name))
|
||||
return;
|
||||
|
||||
if (_customization.Tools.TryGetValue(name, out var customPath) && File.Exists(customPath))
|
||||
{
|
||||
Tools.Add(new ExternalTool(name, icon, customPath, execArgsGenerator, subOptionsFinder));
|
||||
Tools.Add(new ExternalTool(name, icon, customPath, optionsGenerator));
|
||||
}
|
||||
else
|
||||
{
|
||||
var path = finder();
|
||||
if (!string.IsNullOrEmpty(path) && File.Exists(path))
|
||||
Tools.Add(new ExternalTool(name, icon, path, execArgsGenerator, subOptionsFinder));
|
||||
Tools.Add(new ExternalTool(name, icon, path, optionsGenerator));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ namespace SourceGit.Native
|
||||
{
|
||||
var exec = instance.ProductPath;
|
||||
var icon = instance.IsPrerelease ? "vs-preview" : "vs";
|
||||
finder.TryAdd(instance.DisplayName, icon, () => exec, GenerateCommandlineArgsForVisualStudio, FindVisualStudioSolutions);
|
||||
finder.TryAdd(instance.DisplayName, icon, () => exec, GenerateVSProjectLaunchOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,35 +444,34 @@ namespace SourceGit.Native
|
||||
}
|
||||
}
|
||||
|
||||
private string GenerateCommandlineArgsForVisualStudio(string path)
|
||||
private List<Models.ExternalTool.LaunchOption> GenerateVSProjectLaunchOptions(string path)
|
||||
{
|
||||
var solutions = FindVisualStudioSolutions(path);
|
||||
return solutions.Count > 0 ? solutions[0].Quoted() : path.Quoted();
|
||||
}
|
||||
|
||||
public List<string> FindVisualStudioSolutions(string path)
|
||||
{
|
||||
var solutions = new List<string>();
|
||||
if (!Directory.Exists(path))
|
||||
return solutions;
|
||||
|
||||
void Search(DirectoryInfo dir, int depth)
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
if (depth < 0)
|
||||
return;
|
||||
void Search(List<Models.ExternalTool.LaunchOption> opts, DirectoryInfo dir, string root, int depth)
|
||||
{
|
||||
if (depth < 0)
|
||||
return;
|
||||
|
||||
foreach (var file in dir.GetFiles("*.sln"))
|
||||
solutions.Add(file.FullName);
|
||||
foreach (var file in dir.GetFiles())
|
||||
{
|
||||
if (file.Name.EndsWith(".sln", StringComparison.OrdinalIgnoreCase) ||
|
||||
file.Name.EndsWith(".slnx", StringComparison.OrdinalIgnoreCase))
|
||||
opts.Add(new(Path.GetRelativePath(root, file.FullName), file.FullName.Quoted()));
|
||||
}
|
||||
|
||||
foreach (var file in dir.GetFiles("*.slnx"))
|
||||
solutions.Add(file.FullName);
|
||||
foreach (var subDir in dir.GetDirectories())
|
||||
Search(opts, subDir, root, depth - 1);
|
||||
}
|
||||
|
||||
foreach (var subDir in dir.GetDirectories())
|
||||
Search(subDir, depth - 1);
|
||||
var rootDir = new DirectoryInfo(path);
|
||||
var options = new List<Models.ExternalTool.LaunchOption>();
|
||||
Search(options, rootDir, rootDir.FullName, 4);
|
||||
if (options.Count > 0)
|
||||
return options;
|
||||
}
|
||||
Search(new DirectoryInfo(path), 4);
|
||||
|
||||
return solutions;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,6 +729,7 @@
|
||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
|
||||
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">CLEAR NOTIFICATIONS</x:String>
|
||||
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">Only highlight current branch</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenAsFolder" xml:space="preserve">Open as Folder</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open in {0}</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open in External Tools</x:String>
|
||||
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>
|
||||
|
||||
@@ -733,6 +733,7 @@
|
||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String>
|
||||
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">清空通知列表</x:String>
|
||||
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">仅高亮显示当前分支</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenAsFolder" xml:space="preserve">本仓库(文件夹)</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">在 {0} 中打开</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">使用外部工具打开</x:String>
|
||||
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">远程列表</x:String>
|
||||
|
||||
@@ -733,6 +733,7 @@
|
||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新增分支</x:String>
|
||||
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">清除所有通知</x:String>
|
||||
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">路線圖中僅對目前分支上色</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenAsFolder" xml:space="preserve">此存放庫(資料夾)</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">在 {0} 中開啟</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">使用外部工具開啟</x:String>
|
||||
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">遠端列表</x:String>
|
||||
|
||||
@@ -343,7 +343,7 @@ namespace SourceGit.ViewModels
|
||||
if (tool == null)
|
||||
Native.OS.OpenWithDefaultEditor(tmpFile);
|
||||
else
|
||||
tool.Open(tmpFile);
|
||||
tool.Launch(tmpFile.Quoted());
|
||||
}
|
||||
|
||||
public async Task SaveRevisionFileAsync(Models.Object file, string saveTo)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
@@ -63,34 +62,42 @@ namespace SourceGit.Views
|
||||
item.Header = App.Text("Repository.OpenIn", dupTool.Name);
|
||||
item.Icon = new Image { Width = 16, Height = 16, Source = dupTool.IconImage };
|
||||
|
||||
var subOptions = dupTool.FindSubOptions(fullpath);
|
||||
if (subOptions != null && subOptions.Count > 1)
|
||||
var options = dupTool.MakeLaunchOptions(fullpath);
|
||||
if (options is { Count: > 0 })
|
||||
{
|
||||
foreach (var subOption in subOptions)
|
||||
var openAsFolder = new MenuItem();
|
||||
openAsFolder.Header = App.Text("Repository.OpenAsFolder");
|
||||
openAsFolder.Click += (_, e) =>
|
||||
{
|
||||
dupTool.Launch(fullpath.Quoted());
|
||||
e.Handled = true;
|
||||
};
|
||||
item.Items.Add(openAsFolder);
|
||||
item.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
foreach (var opt in options)
|
||||
{
|
||||
var subItem = new MenuItem();
|
||||
subItem.Header = Path.GetFileName(subOption);
|
||||
subItem.Header = opt.Title;
|
||||
subItem.Click += (_, e) =>
|
||||
{
|
||||
dupTool.Open(subOption);
|
||||
dupTool.Launch(opt.Args);
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
item.Items.Add(subItem);
|
||||
}
|
||||
|
||||
menu.Items.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Click += (_, e) =>
|
||||
{
|
||||
dupTool.Open(fullpath);
|
||||
dupTool.Launch(fullpath.Quoted());
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(item);
|
||||
}
|
||||
|
||||
menu.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1290,7 +1290,7 @@ namespace SourceGit.Views
|
||||
item.Icon = new Image { Width = 16, Height = 16, Source = tool.IconImage };
|
||||
item.Click += (_, e) =>
|
||||
{
|
||||
tool.Open(fullpath);
|
||||
tool.Launch(fullpath.Quoted());
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user