diff options
Diffstat (limited to 'nix.go')
| -rw-r--r-- | nix.go | 41 |
1 files changed, 41 insertions, 0 deletions
@@ -0,0 +1,41 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "os" + "os/exec" + "strings" +) + +// managedBy names the tool that installs skills instead of this one, such as +// home-manager. skills then only maintains the lock and the Nix store. +func managedBy() string { return os.Getenv("SKILLS_MANAGED_BY") } + +// nixFetch copies a locked source into the Nix store as the current user and +// returns its narHash. A later evaluation, even by root without this user's +// SSH keys, then finds it there instead of fetching it. +func nixFetch(ctx context.Context, url, rev string) (string, error) { + ref := "git+" + url + "?rev=" + rev + "&allRefs=1" + cmd := exec.CommandContext(ctx, "nix", "--extra-experimental-features", "nix-command flakes", + "flake", "prefetch", "--json", ref) + var stderr bytes.Buffer + cmd.Stderr = &stderr + out, err := cmd.Output() + if errors.Is(err, exec.ErrNotFound) { + return "", fmt.Errorf("SKILLS_MANAGED_BY=%s needs nix, which is not installed", managedBy()) + } + if err != nil { + return "", fmt.Errorf("nix could not fetch %s: %s", url, strings.TrimSpace(stderr.String())) + } + var p struct { + Hash string `json:"hash"` + } + if err := json.Unmarshal(out, &p); err != nil || p.Hash == "" { + return "", fmt.Errorf("unexpected output from nix flake prefetch: %s", out) + } + return p.Hash, nil +} |
