diff --git a/PinAction/Program.cs b/PinAction/Program.cs index ee2398c..cc4e0d0 100644 --- a/PinAction/Program.cs +++ b/PinAction/Program.cs @@ -15,18 +15,14 @@ internal partial class Program /// /// 参数 /// 退出代码 - static int Main(string[] args) + private static int Main(string[] args) { if ( (args.Length == 0) || // 不提供参数 - ( - // 单独提供帮助相关参数 - (args.Length == 1) && - (args[0] is "help" - or "--help" - or "-h" - or "/?") - ) + args is ["help" + or "--help" + or "-h" + or "/?"] ) { Console.WriteLine(Strings.Help); @@ -114,115 +110,111 @@ private static bool PinActionHash(string path) for (int i = 0; i < lines.Length; i++) { - if (lines[i].Contains("uses:")) - { - // 移除注释 - string[] cleanLinePaths = lines[i].Split('#'); + if (!lines[i].Contains("uses:")) continue; - // 非注释内容匹配正则 "^\s+uses:\s*([^@]+)@([^@|\s]+)\s*$" - Match match = UsesRegex().Match(cleanLinePaths[0]); + // 移除注释 + string[] cleanLinePaths = lines[i].Split('#'); - if (match.Success) - { - string repo = match.Groups[1].Value; - string tag = match.Groups[2].Value; + // 非注释内容匹配正则 "^\s+uses:\s*([^@]+)@([^@|\s]+)\s*$" + Match match = UsesRegex().Match(cleanLinePaths[0]); + if (!match.Success) continue; + + string repo = match.Groups[1].Value; + string tag = match.Groups[2].Value; + + AnsiConsole.MarkupLine($"{Print.MSHead.Information} {string.Format(Strings.FindAction, Path.GetRelativePath(Environment.CurrentDirectory, path), Markup.Escape($"{repo}@{tag}"))}"); + + // 在这里你可以定义排除哪些项 + // 例如排除以 actions/ 开头的项(actions/*@*) + // if (repo.StartsWith("actions/")) + // { + // AnsiConsole.MarkupLine($"{Print.MSHead.Warning} 跳过 {repo}@{tag},因为它是官方工作流"); + // continue; + // } - AnsiConsole.MarkupLine($"{Print.MSHead.Information} {string.Format(Strings.FindAction, Path.GetRelativePath(Environment.CurrentDirectory, path), Markup.Escape($"{repo}@{tag}"))}"); - // 在这里你可以定义排除哪些项 - // 例如排除以 actions/ 开头的项(actions/*@*) - // if (repo.StartsWith("actions/")) - // { - // AnsiConsole.MarkupLine($"{Print.MSHead.Warning} 跳过 {repo}@{tag},因为它是官方工作流"); - // continue; - // } + // 操作前检查 + // 检查是否已经是哈希值(40个十六进制字符) + if (HashRegex().IsMatch(tag)) + { + AnsiConsole.MarkupLine($"{Print.MSHead.Information} {string.Format(Strings.SkippingAlreadyPinnedHashes, Markup.Escape($"{repo}@{tag}"))}"); + continue; + } + // 检查仓库是否是 owner/repo 的格式 + if (repo.Split('/').Length != 2) + { + AnsiConsole.MarkupLine($"{Print.MSHead.Warning} {Markup.Escape(repo)} 看起来不像是仓库的格式,跳过 {Markup.Escape($"{repo}@{tag}")}"); + continue; + } - // 操作前检查 - // 检查是否已经是哈希值(40个十六进制字符) - if (HashRegex().IsMatch(tag)) + if (!PinedActions.TryGetValue($"{repo}@{tag}", out string? hash)) + { + // 尝试 tags/{tag} 和 heads/{tag} + foreach (string refType in new[] { "tags", "heads" }) + { + try { - AnsiConsole.MarkupLine($"{Print.MSHead.Information} {string.Format(Strings.SkippingAlreadyPinnedHashes, Markup.Escape($"{repo}@{tag}"))}"); - continue; + // 获取该版本的 git commit hash + Reference reference = GitHubClient.Git.Reference.Get(repo.Split('/')[0], repo.Split('/')[1], $"{refType}/{tag}").Result; + hash = reference.Object.Sha; + + PinedActions.TryAdd($"{repo}@{tag}", hash); + break; } - // 检查仓库是否是 owner/repo 的格式 - if (repo.Split('/').Length != 2) + catch (AggregateException ex) when (ex.InnerException != null) { - AnsiConsole.MarkupLine($"{Print.MSHead.Warning} {Markup.Escape(repo)} 看起来不像是仓库的格式,跳过 {Markup.Escape($"{repo}@{tag}")}"); - continue; - } - + AnsiConsole.Markup($"{Print.MSHead.Warning} {Strings.ErrorGetHashFailed}"); - string? hash; - if (!pinedActions.TryGetValue($"{repo}@{tag}", out hash)) - { - // 尝试 tags/{tag} 和 heads/{tag} - foreach (string refType in new[] { "tags", "heads" }) + switch (ex.InnerException) { - try - { - // 获取该版本的 git commit hash - Reference reference = GitHubClient.Git.Reference.Get(repo.Split('/')[0], repo.Split('/')[1], $"{refType}/{tag}").Result; - hash = reference.Object.Sha; - - pinedActions.TryAdd($"{repo}@{tag}", hash); - break; - } - catch (AggregateException ex) when (ex.InnerException != null) - { - AnsiConsole.Markup($"{Print.MSHead.Warning} {Strings.ErrorGetHashFailed}"); - - switch (ex.InnerException) + // 还要再试的用 break; + // 最后一次的用 continue; + // 直接整个程序失败的 return false; + case Octokit.NotFoundException: + if (refType == "tags") + { + AnsiConsole.MarkupLineInterpolated($"[yellow]{string.Format(Strings.ErrorTagNotFound, tag)}[/]"); + break; + } + else { - // 还要再试的用 break; - // 最后一次的用 continue; - // 直接整个程序失败的 return false; - case Octokit.NotFoundException: - if (refType == "tags") - { - AnsiConsole.MarkupLineInterpolated($"[yellow]{string.Format(Strings.ErrorTagNotFound, tag)}[/]"); - break; - } - else - { - AnsiConsole.MarkupLineInterpolated($"[red]{string.Format(Strings.ErrorBranchNotFound, tag, $"{repo}@{tag}")}[/]"); - continue; - } - case Octokit.RateLimitExceededException: - AnsiConsole.MarkupLine($"[yellow]{Strings.ErrorRateLimitExceeded}[/]"); - return false; - default: - AnsiConsole.MarkupLineInterpolated($"[red]{ex.InnerException.Message}[/]"); - continue; + AnsiConsole.MarkupLineInterpolated($"[red]{string.Format(Strings.ErrorBranchNotFound, tag, $"{repo}@{tag}")}[/]"); + continue; } - } + case Octokit.RateLimitExceededException: + AnsiConsole.MarkupLine($"[yellow]{Strings.ErrorRateLimitExceeded}[/]"); + return false; + default: + AnsiConsole.MarkupLineInterpolated($"[red]{ex.InnerException.Message}[/]"); + continue; } } + } + } #if DEBUG - else - { - AnsiConsole.MarkupLine($"{Print.MSHead.Debug} 读取缓存 {Markup.Escape($"{repo}@{hash}")} # {Markup.Escape(tag)}"); - } + else + { + AnsiConsole.MarkupLine($"{Print.MSHead.Debug} 读取缓存 {Markup.Escape($"{repo}@{hash}")} # {Markup.Escape(tag)}"); + } #endif - if (hash is null) - { - continue; - } - - lines[i] = $"{cleanLinePaths[0].Replace($"{repo}@{tag}", $"{repo}@{hash}")} # {tag}"; - if (cleanLinePaths.Length > 1) - { - // 将注释部分重新添加到行末 - foreach (string commentPart in cleanLinePaths.Skip(1)) - { - lines[i] += commentPart; - } - } + if (hash is null) + { + continue; + } - AnsiConsole.MarkupLine($"{Print.MSHead.Success} {Strings.Pinned} {Markup.Escape($"{repo}@{hash}")} # {Markup.Escape(tag)}"); + lines[i] = $"{cleanLinePaths[0].Replace($"{repo}@{tag}", $"{repo}@{hash}")} # {tag}"; + if (cleanLinePaths.Length > 1) + { + // 将注释部分重新添加到行末 + foreach (string commentPart in cleanLinePaths.Skip(1)) + { + lines[i] += commentPart; } } + + AnsiConsole.MarkupLine($"{Print.MSHead.Success} {Strings.Pinned} {Markup.Escape($"{repo}@{hash}")} # {Markup.Escape(tag)}"); } // 将修改后的内容写回文件 @@ -241,7 +233,7 @@ private static bool PinActionHash(string path) /// 缓存已固定哈希值的 Action,第二次遇到时不用再去请求 GitHub API 获取。 /// repo@tag, hash 一对存储。 /// - private static readonly ConcurrentDictionary pinedActions = new(); + private static readonly ConcurrentDictionary PinedActions = new(); [GeneratedRegex(@"^\s*uses:\s*([^@]+)@([^@|\s]+)\s*$")] private static partial Regex UsesRegex();