Skip to content

Commit 94df293

Browse files
committed
[rm nixpkgs] make HEAD request to BinaryCache to ensure binary is cached
1 parent afeec38 commit 94df293

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

internal/devpkg/package.go

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import (
88
"encoding/hex"
99
"fmt"
1010
"io"
11+
"net/http"
1112
"net/url"
13+
"os"
1214
"path/filepath"
1315
"regexp"
1416
"strings"
17+
"time"
1518

1619
"github.com/pkg/errors"
1720
"github.com/samber/lo"
@@ -53,6 +56,12 @@ type Package struct {
5356
normalizedPackageAttributePathCache string // memoized value from normalizedPackageAttributePath()
5457
}
5558

59+
// isNarInfoInCache checks if the .narinfo for this package is in the `BinaryCache`.
60+
// The key is the `Package.Raw` string.
61+
// This cannot be a field on the Package struct, because that struct
62+
// is constructed multiple times in a request (TODO: we could fix that).
63+
var isNarInfoInCache = map[string]bool{}
64+
5665
// PackageFromStrings constructs Package from the list of package names provided.
5766
// These names correspond to devbox packages from the devbox.json config.
5867
func PackageFromStrings(rawNames []string, l lock.Locker) []*Package {
@@ -481,7 +490,7 @@ func (p *Package) IsInBinaryCache() (bool, error) {
481490
}
482491

483492
// Check if the user's system's info is present in the lockfile
484-
_, ok := entry.Systems[nix.System()]
493+
sysInfo, ok := entry.Systems[nix.System()]
485494
if !ok {
486495
return false, nil
487496
}
@@ -492,7 +501,33 @@ func (p *Package) IsInBinaryCache() (bool, error) {
492501
}
493502

494503
// enable for nix >= 2.17
495-
return vercheck.SemverCompare(version, "2.17.0") >= 0, nil
504+
if vercheck.SemverCompare(version, "2.17.0") < 0 {
505+
return false, nil
506+
}
507+
508+
// Check if the narinfo is present in the binary cache
509+
if exists, ok := isNarInfoInCache[p.Raw]; ok {
510+
fmt.Printf("narInfo cache hit: %v\n", exists)
511+
return exists, nil
512+
}
513+
514+
httpClient := &http.Client{
515+
Timeout: time.Second * 5,
516+
}
517+
pathParts := newStorePathParts(sysInfo.StorePath)
518+
reqURL := BinaryCache + "/" + pathParts.hash + ".narinfo"
519+
res, err := httpClient.Head(reqURL)
520+
if err != nil {
521+
if os.IsTimeout(err) {
522+
isNarInfoInCache[p.Raw] = false // set this to avoid re-tries
523+
return false, nil
524+
}
525+
return false, err
526+
}
527+
fmt.Printf("res status code %d\n", res.StatusCode)
528+
529+
isNarInfoInCache[p.Raw] = res.StatusCode == 200
530+
return isNarInfoInCache[p.Raw], nil
496531
}
497532

498533
// InputAddressedPath is the input-addressed path in /nix/store
@@ -542,3 +577,30 @@ func (p *Package) EnsureUninstallableIsInLockfile() error {
542577
_, err := p.lockfile.Resolve(p.Raw)
543578
return err
544579
}
580+
581+
// storePath are the constituent parts of
582+
// /nix/store/<hash>-<name>-<version>
583+
//
584+
// This is a helper struct for analyzing the string representation
585+
type storePathParts struct {
586+
hash string
587+
name string
588+
version string
589+
}
590+
591+
func newStorePathParts(path string) *storePathParts {
592+
path = strings.TrimPrefix(path, "/nix/store/")
593+
// path is now <hash>-<name>-<version
594+
parts := strings.Split(path, "-")
595+
596+
// writing this a bit defensively to avoid edge-cases that may break
597+
var hash, name, version string
598+
hash = parts[0]
599+
if len(parts) > 1 {
600+
name = parts[1]
601+
}
602+
if len(parts) > 2 {
603+
version = parts[2]
604+
}
605+
return &storePathParts{hash, name, version}
606+
}

0 commit comments

Comments
 (0)