feat: multi-solution management (#2043)

This commit is contained in:
ギャップ
2026-01-13 03:31:55 +01:00
committed by GitHub
parent 96e2754bac
commit 3dbab1c7bf
3 changed files with 65 additions and 36 deletions

View File

@@ -16,11 +16,12 @@ namespace SourceGit.Models
public string ExecFile { get; }
public Bitmap IconImage { get; }
public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null)
public ExternalTool(string name, string icon, string execFile, Func<string, string> execArgsGenerator = null, Func<string, List<string>> subOptionsFinder = null)
{
Name = name;
ExecFile = execFile;
_execArgsGenerator = execArgsGenerator ?? (path => path.Quoted());
_subOptionsFinder = subOptionsFinder;
try
{
@@ -48,7 +49,16 @@ namespace SourceGit.Models
});
}
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;
}
public class VisualStudioInstance
@@ -130,20 +140,20 @@ namespace SourceGit.Models
_customization ??= new ExternalToolCustomization();
}
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null)
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null, Func<string, List<string>> subOptionsFinder = 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));
Tools.Add(new ExternalTool(name, icon, customPath, execArgsGenerator, subOptionsFinder));
}
else
{
var path = finder();
if (!string.IsNullOrEmpty(path) && File.Exists(path))
Tools.Add(new ExternalTool(name, icon, path, execArgsGenerator));
Tools.Add(new ExternalTool(name, icon, path, execArgsGenerator, subOptionsFinder));
}
}

View File

@@ -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);
finder.TryAdd(instance.DisplayName, icon, () => exec, GenerateCommandlineArgsForVisualStudio, FindVisualStudioSolutions);
}
}
}
@@ -446,37 +446,33 @@ namespace SourceGit.Native
private string GenerateCommandlineArgsForVisualStudio(string path)
{
if (Directory.Exists(path))
{
var sln = FindVSSolutionFile(new DirectoryInfo(path), 4);
return string.IsNullOrEmpty(sln) ? path.Quoted() : sln.Quoted();
}
return path.Quoted();
var solutions = FindVisualStudioSolutions(path);
return solutions.Count > 0 ? solutions[0].Quoted() : path.Quoted();
}
private string FindVSSolutionFile(DirectoryInfo dir, int leftDepth)
public List<string> FindVisualStudioSolutions(string path)
{
var files = dir.GetFiles();
foreach (var f in files)
var solutions = new List<string>();
if (!Directory.Exists(path))
return solutions;
void Search(DirectoryInfo dir, int depth)
{
if (f.Name.EndsWith(".slnx", StringComparison.OrdinalIgnoreCase) ||
f.Name.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))
return f.FullName;
if (depth < 0)
return;
foreach (var file in dir.GetFiles("*.sln"))
solutions.Add(file.FullName);
foreach (var file in dir.GetFiles("*.slnx"))
solutions.Add(file.FullName);
foreach (var subDir in dir.GetDirectories())
Search(subDir, depth - 1);
}
Search(new DirectoryInfo(path), 4);
if (leftDepth <= 0)
return null;
var subDirs = dir.GetDirectories();
foreach (var subDir in subDirs)
{
var first = FindVSSolutionFile(subDir, leftDepth - 1);
if (!string.IsNullOrEmpty(first))
return first;
}
return null;
return solutions;
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
using Avalonia.Controls;
using Avalonia.Input;
@@ -61,13 +62,35 @@ namespace SourceGit.Views
var item = new MenuItem();
item.Header = App.Text("Repository.OpenIn", dupTool.Name);
item.Icon = new Image { Width = 16, Height = 16, Source = dupTool.IconImage };
item.Click += (_, e) =>
{
dupTool.Open(fullpath);
e.Handled = true;
};
menu.Items.Add(item);
var subOptions = dupTool.FindSubOptions(fullpath);
if (subOptions != null && subOptions.Count > 1)
{
foreach (var subOption in subOptions)
{
var subItem = new MenuItem();
subItem.Header = Path.GetFileName(subOption);
subItem.Click += (_, e) =>
{
dupTool.Open(subOption);
e.Handled = true;
};
item.Items.Add(subItem);
}
menu.Items.Add(item);
}
else
{
item.Click += (_, e) =>
{
dupTool.Open(fullpath);
e.Handled = true;
};
menu.Items.Add(item);
}
}
}