Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions plugins/VelaShell.Plugin.DockerPanel/Docker/BatchRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ public static async Task<BatchResult> RunAsync<T>(
CancellationToken cancellationToken = default)
{
List<BatchOutcome> outcomes = [with(targets.Count)];
for (var i = 0; i < targets.Count; i++)
for (int i = 0; i < targets.Count; i++)
{
(var target, var name) = targets[i];
(T? target, string? name) = targets[i];
if (cancellationToken.IsCancellationRequested)
{
outcomes.Add(new(name, false, "已取消,这个目标没有执行。"));
Expand All @@ -73,7 +73,7 @@ public static async Task<BatchResult> RunAsync<T>(
{
// 连接没了就没有必要继续戳后面的目标 —— 它们只会拿到同一条错误。
outcomes.Add(new(name, false, ex.Message));
for (var j = i + 1; j < targets.Count; j++)
for (int j = i + 1; j < targets.Count; j++)
{
outcomes.Add(new(targets[j].Name, false, "连接已断开,这个目标没有执行。"));
}
Expand Down
26 changes: 13 additions & 13 deletions plugins/VelaShell.Plugin.DockerPanel/Docker/ComposeCli.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ public sealed record ComposeProject(string Name, string Status, string ConfigFil

private int ParseCount(string keyword)
{
var at = Status.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
int at = Status.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
if (at < 0)
{
return 0;
}
var open = Status.IndexOf('(', at);
var close = open > 0 ? Status.IndexOf(')', open) : -1;
return close > open && int.TryParse(Status.AsSpan(open + 1, close - open - 1), out var n) ? n : 0;
int open = Status.IndexOf('(', at);
int close = open > 0 ? Status.IndexOf(')', open) : -1;
return close > open && int.TryParse(Status.AsSpan(open + 1, close - open - 1), out int n) ? n : 0;
}
}

Expand Down Expand Up @@ -88,11 +88,11 @@ public string PortsText
{
return "—";
}
var parts = Publishers
IEnumerable<string> parts = Publishers
.Where(p => p.PublishedPort > 0)
.Select(p => $"{p.PublishedPort}→{p.TargetPort}")
.Distinct();
var text = string.Join(", ", parts);
string text = string.Join(", ", parts);
return text.Length == 0 ? "—" : text;
}
}
Expand Down Expand Up @@ -143,7 +143,7 @@ public sealed class ComposeCli(IComposeHost host)
/// </summary>
public async Task<ComposeProject[]> ListProjectsAsync(CancellationToken cancellationToken = default)
{
var result = await host
ExecResult result = await host
.RunAsync(["compose", "ls", "--all", "--format", "json"], TimeSpan.FromSeconds(20), cancellationToken)
.ConfigureAwait(false);
if (!result.IsSuccess)
Expand All @@ -152,7 +152,7 @@ public async Task<ComposeProject[]> ListProjectsAsync(CancellationToken cancella
// 上层的提示,而不是把一条看不懂的错误摔在用户脸上。
return [];
}
var entries = DockerJson.TryDeserialize<ComposeListEntry[]>(result.Output.Trim());
ComposeListEntry[]? entries = DockerJson.TryDeserialize<ComposeListEntry[]>(result.Output.Trim());
return entries is null
? []
: [.. entries.Select(e => new ComposeProject(e.Name ?? "", e.Status ?? "", e.ConfigFiles ?? ""))];
Expand All @@ -161,14 +161,14 @@ public async Task<ComposeProject[]> ListProjectsAsync(CancellationToken cancella
/// <summary>列出项目里的服务。</summary>
public async Task<ComposeService[]> ListServicesAsync(ComposeProject project, CancellationToken cancellationToken = default)
{
var result = await host
ExecResult result = await host
.RunAsync([.. Prefix(project), "ps", "-a", "--format", "json"], TimeSpan.FromSeconds(20), cancellationToken)
.ConfigureAwait(false);
if (!result.IsSuccess)
{
return [];
}
var text = result.Output.Trim();
string text = result.Output.Trim();
if (text.Length == 0)
{
return [];
Expand All @@ -180,7 +180,7 @@ public async Task<ComposeService[]> ListServicesAsync(ComposeProject project, Ca
return DockerJson.TryDeserialize<ComposeService[]>(text) ?? [];
}
List<ComposeService> services = [];
foreach (var line in text.Split('\n', StringSplitOptions.RemoveEmptyEntries))
foreach (string line in text.Split('\n', StringSplitOptions.RemoveEmptyEntries))
{
if (DockerJson.TryDeserialize<ComposeService>(line.Trim()) is { } service)
{
Expand Down Expand Up @@ -250,7 +250,7 @@ public async Task<bool> IsAvailableAsync(CancellationToken cancellationToken = d
{
try
{
var result = await host
ExecResult result = await host
.RunAsync(["compose", "version", "--short"], TimeSpan.FromSeconds(15), cancellationToken)
.ConfigureAwait(false);
return result.IsSuccess;
Expand All @@ -275,7 +275,7 @@ public async Task<bool> IsAvailableAsync(CancellationToken cancellationToken = d
private static List<string> Prefix(ComposeProject project)
{
List<string> argv = ["compose", "-p", project.Name];
foreach (var file in project.ConfigFiles.Split(',', StringSplitOptions.RemoveEmptyEntries))
foreach (string file in project.ConfigFiles.Split(',', StringSplitOptions.RemoveEmptyEntries))
{
argv.Add("-f");
argv.Add(file.Trim());
Expand Down
6 changes: 3 additions & 3 deletions plugins/VelaShell.Plugin.DockerPanel/Docker/ComposeHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public Task<ExecResult> RunAsync(IReadOnlyList<string> arguments, TimeSpan timeo
public async Task<int> StreamAsync(IReadOnlyList<string> arguments, IProgress<ExecOutput> output,
CancellationToken cancellationToken = default)
{
var result = await exec
ExecStreamResult result = await exec
.StreamAsync(sessionId, Join(arguments), new ExecStreamOptions { IncludeStandardError = true },
output, cancellationToken)
.ConfigureAwait(false);
Expand All @@ -67,7 +67,7 @@ public async Task<int> StreamAsync(IReadOnlyList<string> arguments, IProgress<Ex
/// <inheritdoc />
public async Task<string> ReadFileAsync(string path, CancellationToken cancellationToken = default)
{
var bytes = await remoteFs.ReadAllBytesAsync(sessionId, path, 4 << 20, cancellationToken)
byte[] bytes = await remoteFs.ReadAllBytesAsync(sessionId, path, 4 << 20, cancellationToken)
.ConfigureAwait(false);
return Encoding.UTF8.GetString(bytes);
}
Expand Down Expand Up @@ -168,7 +168,7 @@ private static async Task<int> PumpAsync(IReadOnlyList<string> arguments, Action
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8
};
foreach (var argument in arguments)
foreach (string argument in arguments)
{
info.ArgumentList.Add(argument);
}
Expand Down
8 changes: 4 additions & 4 deletions plugins/VelaShell.Plugin.DockerPanel/Docker/ComposePath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ internal static bool IsAbsolute(string path) =>
/// <summary>去掉最后一段(取所在目录);没有分隔符就原样返回。</summary>
internal static string DirectoryOf(string path)
{
var trimmed = path.TrimEnd(Separators);
var slash = trimmed.LastIndexOfAny(Separators);
string trimmed = path.TrimEnd(Separators);
int slash = trimmed.LastIndexOfAny(Separators);
return slash > 0 ? trimmed[..slash] : trimmed;
}

/// <summary>取最后一段(目录名 / 文件名)。</summary>
internal static string LastSegment(string path)
{
var trimmed = path.TrimEnd(Separators);
var slash = trimmed.LastIndexOfAny(Separators);
string trimmed = path.TrimEnd(Separators);
int slash = trimmed.LastIndexOfAny(Separators);
return slash >= 0 ? trimmed[(slash + 1)..] : trimmed;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public Task<ContainerTopResult> TopAsync(string id, string psArgs = "-ef", Cance
public async Task<FilesystemChange[]> ChangesAsync(string id, CancellationToken cancellationToken = default)
{
// 没有任何变更时 daemon 返回 JSON null,不是空数组。
var body = await GetStringAsync($"/containers/{Uri.EscapeDataString(id)}/changes", cancellationToken).ConfigureAwait(false);
string body = await GetStringAsync($"/containers/{Uri.EscapeDataString(id)}/changes", cancellationToken).ConfigureAwait(false);
return DockerJson.TryDeserialize<FilesystemChange[]>(body) ?? [];
}

Expand Down
28 changes: 14 additions & 14 deletions plugins/VelaShell.Plugin.DockerPanel/Docker/DockerClient.Exec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ public string FailureText
{
get
{
foreach (var candidate in new[] { StandardError, StandardOutput })
foreach (string? candidate in new[] { StandardError, StandardOutput })
{
foreach (var line in candidate.Split('\n'))
foreach (string line in candidate.Split('\n'))
{
var trimmed = line.Trim();
string trimmed = line.Trim();
if (trimmed.Length > 0)
{
return trimmed;
Expand Down Expand Up @@ -98,15 +98,15 @@ public sealed partial class DockerClient
public async Task<DockerExecSession> StartExecAsync(string containerId, string[] command, bool tty,
string? user = null, string? workingDir = null, CancellationToken cancellationToken = default)
{
var created = await CreateExecAsync(containerId, command, tty, attachStdin: true, user, workingDir,
ExecCreateResponse created = await CreateExecAsync(containerId, command, tty, attachStdin: true, user, workingDir,
cancellationToken).ConfigureAwait(false);
// 劫持端点要独占一条流:HttpClient 的连接池不能用,它没法在同一条连接上
// 边写 stdin 边读 stdout。
var stream = await Transport.ConnectAsync(cancellationToken).ConfigureAwait(false);
Stream stream = await Transport.ConnectAsync(cancellationToken).ConfigureAwait(false);
try
{
var body = JsonSerializer.Serialize(new { Detach = false, Tty = tty }, DockerJson.Options);
(var status, var reason, var hijacked) = await DockerRawHttp
string body = JsonSerializer.Serialize(new { Detach = false, Tty = tty }, DockerJson.Options);
(int status, string? reason, Stream? hijacked) = await DockerRawHttp
.PostAsync(stream, $"/exec/{Uri.EscapeDataString(created.Id)}/start", body, upgrade: true, cancellationToken)
.ConfigureAwait(false);
return status is not (200 or 101) ? throw new DockerApiException((System.Net.HttpStatusCode)status, $"启动 exec 失败:HTTP {status} {reason}") : new(created.Id, hijacked, this, tty);
Expand All @@ -129,15 +129,15 @@ public async Task<DockerExecSession> StartExecAsync(string containerId, string[]
public async Task<ExecCapture> ExecCaptureAsync(string containerId, string[] command,
string? user = null, string? workingDir = null, CancellationToken cancellationToken = default)
{
var created = await CreateExecAsync(containerId, command, tty: false, attachStdin: false,
ExecCreateResponse created = await CreateExecAsync(containerId, command, tty: false, attachStdin: false,
user, workingDir, cancellationToken).ConfigureAwait(false);
var stream = await Transport.ConnectAsync(cancellationToken).ConfigureAwait(false);
Stream stream = await Transport.ConnectAsync(cancellationToken).ConfigureAwait(false);
var stdout = new StringBuilder();
var stderr = new StringBuilder();
await using (stream.ConfigureAwait(false))
{
var body = JsonSerializer.Serialize(new { Detach = false, Tty = false }, DockerJson.Options);
(var status, var reason, var hijacked) = await DockerRawHttp
string body = JsonSerializer.Serialize(new { Detach = false, Tty = false }, DockerJson.Options);
(int status, string? reason, Stream? hijacked) = await DockerRawHttp
.PostAsync(stream, $"/exec/{Uri.EscapeDataString(created.Id)}/start", body, upgrade: true, cancellationToken)
.ConfigureAwait(false);
if (status is not (200 or 101))
Expand All @@ -147,11 +147,11 @@ public async Task<ExecCapture> ExecCaptureAsync(string containerId, string[] com
var decoder = new DockerFrameDecoder(tty: false, timestamps: false);
await decoder.ReadAsync(hijacked, line =>
{
var target = line.Kind == DockerStreamKind.StdErr ? stderr : stdout;
target.Append(line.Text).Append('\n');
StringBuilder target = line.Kind == DockerStreamKind.StdErr ? stderr : stdout;
_ = target.Append(line.Text).Append('\n');
}, cancellationToken).ConfigureAwait(false);
}
var inspect = await InspectExecAsync(created.Id, cancellationToken).ConfigureAwait(false);
ExecInspectResponse inspect = await InspectExecAsync(created.Id, cancellationToken).ConfigureAwait(false);
return new(stdout.ToString(), stderr.ToString(), inspect.ExitCode);
}

Expand Down
Loading
Loading