| 228 | } |
| 229 | |
| 230 | func parseInfo(data []byte) (Info, error) { |
| 231 | // Example nix --version --debug output from Nix versions 2.12 to 2.21. |
| 232 | // Version 2.12 omits the data directory, but they're otherwise |
| 233 | // identical. |
| 234 | // |
| 235 | // See https://github.com/NixOS/nix/blob/5b9cb8b3722b85191ee8cce8f0993170e0fc234c/src/libmain/shared.cc#L284-L305 |
| 236 | // |
| 237 | // nix (Nix) 2.21.2 |
| 238 | // System type: aarch64-darwin |
| 239 | // Additional system types: x86_64-darwin |
| 240 | // Features: gc, signed-caches |
| 241 | // System configuration file: /etc/nix/nix.conf |
| 242 | // User configuration files: /Users/nobody/.config/nix/nix.conf:/etc/xdg/nix/nix.conf |
| 243 | // Store directory: /nix/store |
| 244 | // State directory: /nix/var/nix |
| 245 | // Data directory: /nix/store/m0ns07v8by0458yp6k30rfq1rs3kaz6g-nix-2.21.2/share |
| 246 | |
| 247 | info := Info{} |
| 248 | if len(data) == 0 { |
| 249 | return info, redact.Errorf("empty nix --version output") |
| 250 | } |
| 251 | |
| 252 | lines := strings.Split(string(data), "\n") |
| 253 | matches := versionRegexp.FindStringSubmatch(lines[0]) |
| 254 | if len(matches) < 3 { |
| 255 | return info, redact.Errorf("parse nix version: %s", redact.Safe(lines[0])) |
| 256 | } |
| 257 | info.Name = matches[1] |
| 258 | info.Version = matches[2] |
| 259 | for _, line := range lines { |
| 260 | name, value, found := strings.Cut(line, ": ") |
| 261 | if !found { |
| 262 | continue |
| 263 | } |
| 264 | |
| 265 | switch name { |
| 266 | case "System type": |
| 267 | info.System = value |
| 268 | case "Additional system types": |
| 269 | info.ExtraSystems = strings.Split(value, ", ") |
| 270 | case "Features": |
| 271 | info.Features = strings.Split(value, ", ") |
| 272 | case "System configuration file": |
| 273 | info.SystemConfig = value |
| 274 | case "User configuration files": |
| 275 | info.UserConfigs = strings.Split(value, ":") |
| 276 | case "Store directory": |
| 277 | info.StoreDir = value |
| 278 | case "State directory": |
| 279 | info.StateDir = value |
| 280 | case "Data directory": |
| 281 | info.DataDir = value |
| 282 | } |
| 283 | } |
| 284 | return info, nil |
| 285 | } |
| 286 | |
| 287 | // AtLeast returns true if i.Version is >= version per semantic versioning. It |