normalizePackageAttributePath calls nix search to find the normalized attribute path. It may be an expensive call (~100ms).
()
| 382 | // normalizePackageAttributePath calls nix search to find the normalized attribute |
| 383 | // path. It may be an expensive call (~100ms). |
| 384 | func (p *Package) normalizePackageAttributePath() (string, error) { |
| 385 | installable, err := p.FlakeInstallable() |
| 386 | if err != nil { |
| 387 | return "", err |
| 388 | } |
| 389 | installable.Outputs = "" |
| 390 | query := installable.String() |
| 391 | if query == "" { |
| 392 | query = p.Raw |
| 393 | } |
| 394 | |
| 395 | // We prefer nix.Search over just trying to parse the package's "URL" because |
| 396 | // nix.Search will guarantee that the package exists for the current system. |
| 397 | var infos map[string]*nix.PkgInfo |
| 398 | if p.IsDevboxPackage && !p.IsRunX() { |
| 399 | // Perf optimization: For queries of the form nixpkgs/<commit>#foo, we can |
| 400 | // use a nix.Search cache. |
| 401 | // |
| 402 | // This will be slow if its the first time on the user's machine that this |
| 403 | // query is running. Otherwise, it will be cached and fast. |
| 404 | if infos, err = nix.SearchNixpkgsAttribute(query); err != nil { |
| 405 | return "", err |
| 406 | } |
| 407 | } else { |
| 408 | // fallback to the slow but generalized nix.Search |
| 409 | if infos, err = nix.Search(query); err != nil { |
| 410 | return "", err |
| 411 | } |
| 412 | } |
| 413 | |
| 414 | if len(infos) == 1 { |
| 415 | return lo.Keys(infos)[0], nil |
| 416 | } |
| 417 | |
| 418 | // If ambiguous, try to find a default output |
| 419 | if len(infos) > 1 && p.installable.AttrPath == "" { |
| 420 | for key := range infos { |
| 421 | if strings.HasSuffix(key, ".default") { |
| 422 | return key, nil |
| 423 | } |
| 424 | } |
| 425 | for key := range infos { |
| 426 | if strings.HasPrefix(key, "defaultPackage.") { |
| 427 | return key, nil |
| 428 | } |
| 429 | } |
| 430 | } |
| 431 | |
| 432 | // Still ambiguous, return error |
| 433 | if len(infos) > 1 { |
| 434 | outputs := fmt.Sprintf("It has %d possible outputs", len(infos)) |
| 435 | if len(infos) < 10 { |
| 436 | outputs = "It has the following possible outputs: \n" + |
| 437 | strings.Join(lo.Keys(infos), ", ") |
| 438 | } |
| 439 | return "", usererr.New( |
| 440 | "Package \"%s\" is ambiguous. %s", |
| 441 | p.Raw, |
no test coverage detected