|
4 | 4 | "fmt" |
5 | 5 | "os" |
6 | 6 | "path/filepath" |
| 7 | + "strconv" |
7 | 8 | "strings" |
8 | 9 | "yc-agent/internal/capture/executils" |
9 | 10 | "yc-agent/internal/config" |
@@ -53,10 +54,86 @@ func ensureDotnetToolResolved() (string, error) { |
53 | 54 | return resolved, nil |
54 | 55 | } |
55 | 56 |
|
| 57 | +func tryParsePid(value string) (int, bool) { |
| 58 | + if value == "" { |
| 59 | + return 0, false |
| 60 | + } |
| 61 | + pid, err := strconv.Atoi(value) |
| 62 | + if err != nil || pid <= 0 { |
| 63 | + return 0, false |
| 64 | + } |
| 65 | + return pid, true |
| 66 | +} |
| 67 | + |
| 68 | +// extractTargetPidFromArgs supports flexible argument ordering, including: |
| 69 | +// - "-p 1234" / "--pid 1234" |
| 70 | +// - "-p=1234" / "--pid=1234" |
| 71 | +// - positional numeric argument (legacy/fallback) |
| 72 | +func extractTargetPidFromArgs(args []string) (int, bool) { |
| 73 | + // Prefer explicit pid flags first. |
| 74 | + for i := 0; i < len(args); i++ { |
| 75 | + arg := strings.TrimSpace(args[i]) |
| 76 | + switch { |
| 77 | + case arg == "-p" || arg == "--pid": |
| 78 | + if i+1 < len(args) { |
| 79 | + if pid, ok := tryParsePid(strings.TrimSpace(args[i+1])); ok { |
| 80 | + return pid, true |
| 81 | + } |
| 82 | + } |
| 83 | + case strings.HasPrefix(arg, "-p="): |
| 84 | + if pid, ok := tryParsePid(strings.TrimPrefix(arg, "-p=")); ok { |
| 85 | + return pid, true |
| 86 | + } |
| 87 | + case strings.HasPrefix(arg, "--pid="): |
| 88 | + if pid, ok := tryParsePid(strings.TrimPrefix(arg, "--pid=")); ok { |
| 89 | + return pid, true |
| 90 | + } |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + // Fallback: first positive integer token in args. |
| 95 | + for _, arg := range args { |
| 96 | + if pid, ok := tryParsePid(strings.TrimSpace(arg)); ok { |
| 97 | + return pid, true |
| 98 | + } |
| 99 | + } |
| 100 | + return 0, false |
| 101 | +} |
| 102 | + |
| 103 | +// resolveDotnetToolForArgs picks the best .NET helper binary for the command: |
| 104 | +// - If user configured DotnetToolPath explicitly, keep using it. |
| 105 | +// - Else, if a target PID can be extracted from args, prefer architecture-specific |
| 106 | +// helper (yc-dot-net-x86.exe / yc-dot-net-x64.exe) and fall back to default resolver. |
| 107 | +func resolveDotnetToolForArgs(args []string) (string, error) { |
| 108 | + if path := config.GlobalConfig.DotnetToolPath; path != "" { |
| 109 | + return path, nil |
| 110 | + } |
| 111 | + |
| 112 | + // Reuse the canonical pid parsed by config flags first (-p can appear anywhere). |
| 113 | + if pid, ok := tryParsePid(strings.TrimSpace(config.GlobalConfig.Pid)); ok { |
| 114 | + if tool, found, err := resolveDotnetToolByPid(pid); err != nil { |
| 115 | + return "", err |
| 116 | + } else if found { |
| 117 | + return tool, nil |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + // Fallback for direct/internal invocations that bypass GlobalConfig parsing. |
| 122 | + if pid, ok := extractTargetPidFromArgs(args); ok { |
| 123 | + if tool, found, err := resolveDotnetToolByPid(pid); err != nil { |
| 124 | + return "", err |
| 125 | + } else if found { |
| 126 | + return tool, nil |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + return ensureDotnetToolResolved() |
| 131 | +} |
| 132 | + |
56 | 133 | // executeDotnetTool runs the configured .NET helper executable with the given arguments |
57 | 134 | // and captures the output to a file. Returns the file handle and any error. |
58 | 135 | func executeDotnetTool(args []string, outputPath string) (*os.File, error) { |
59 | | - toolPath, err := ensureDotnetToolResolved() |
| 136 | + toolPath, err := resolveDotnetToolForArgs(args) |
60 | 137 | if err != nil { |
61 | 138 | return nil, err |
62 | 139 | } |
@@ -147,7 +224,7 @@ func executeDotnetTool(args []string, outputPath string) (*os.File, error) { |
147 | 224 | // startDotnetToolInBackground starts the configured .NET helper executable with the |
148 | 225 | // given arguments and returns the running command handle without waiting. |
149 | 226 | func startDotnetToolInBackground(args []string, hookers ...executils.Hooker) (executils.CmdManager, error) { |
150 | | - toolPath, err := ensureDotnetToolResolved() |
| 227 | + toolPath, err := resolveDotnetToolForArgs(args) |
151 | 228 | if err != nil { |
152 | 229 | return nil, err |
153 | 230 | } |
|
0 commit comments