Skip to content

Commit

Permalink
use json interface of nix-editor
Browse files Browse the repository at this point in the history
  • Loading branch information
ryantm committed Oct 14, 2023
1 parent 2ca030e commit 00b83fd
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 45 deletions.
15 changes: 7 additions & 8 deletions internal/backends/python/python.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,21 +306,20 @@ func pythonMakeBackend(name string, python string) api.LanguageBackend {
}),
Guess: func() (map[api.PkgName]bool, bool) { return guess(python) },
InstallReplitNixSystemDependencies: func(pkgs []api.PkgName) {
ops := []nix.NixEditorOp{}
for _, pkg := range pkgs {
deps := nix.PythonNixDeps(string(pkg))
cmds := nix.ReplitNixAddToNixEditorCmds(deps)
nix.RunNixEditorCmds(cmds)
ops = append(ops, nix.ReplitNixAddToNixEditorOps(deps)...)
}

specfilePkgs, err := listSpecfile()
if err != nil {
return
}
// Ignore the error here, because if we can't read the specfile,
// we still want to add the deps from above at least.
specfilePkgs, _ := listSpecfile()
for pkg := range specfilePkgs {
deps := nix.PythonNixDeps(string(pkg))
cmds := nix.ReplitNixAddToNixEditorCmds(deps)
nix.RunNixEditorCmds(cmds)
ops = append(ops, nix.ReplitNixAddToNixEditorOps(deps)...)
}
nix.RunNixEditorOps(ops)
},
}
}
Expand Down
100 changes: 76 additions & 24 deletions internal/nix/nix.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
package nix

import (
"bytes"
_ "embed"
"encoding/json"
"errors"
"io"
"log"
"os"
"os/exec"
"path"

"github.com/replit/upm/internal/api"
"github.com/replit/upm/internal/util"
)

type NixEditorDepType string

const (
Regular NixEditorDepType = "regular"
Python NixEditorDepType = "python"
)

type NixEditorOp struct {
Op string `json:"op"`
DepType NixEditorDepType `json:"dep_type"`
Dep string `json:"dep"`
}

type ReplitNixAdd struct {
Deps []string `json:"deps,omitempty"`
PythonLibraryDeps []string `json:"libdeps,omitempty"`
Expand Down Expand Up @@ -50,41 +67,76 @@ func PythonNixDeps(pack string) ReplitNixAdd {
return val
}

func ReplitNixAddToNixEditorCmds(replitNixAdd ReplitNixAdd) [][]string {
result := [][]string{}
func ReplitNixAddToNixEditorOps(replitNixAdd ReplitNixAdd) []NixEditorOp {
result := []NixEditorOp{}
for _, dep := range replitNixAdd.Deps {
result = append(result, NixEditorOp{Op: "add", Dep: dep, DepType: Regular})
}
for _, dep := range replitNixAdd.PythonLibraryDeps {
result = append(result, NixEditorOp{Op: "add", Dep: dep, DepType: Python})
}
return result
}

func RunNixEditorOps(ops []NixEditorOp) {
repl_home := os.Getenv("REPL_HOME")
if repl_home == "" {
util.Die("REPL_HOME was not set")
}
path := path.Join(repl_home, "replit.nix")

for _, dep := range replitNixAdd.Deps {
result = append(result, []string{"nix-editor", "--path", path, "--add", dep})
cmd := exec.Command("nix-editor", "--path", path)
stdin, err := cmd.StdinPipe()
if err != nil {
util.Die("couldn't make stdin pipe to nix-editor")
}

for _, dep := range replitNixAdd.PythonLibraryDeps {
result = append(result, []string{"nix-editor", "--path", path, "--dep-type", "python", "--add", dep})
stdout, err := cmd.StdoutPipe()
if err != nil {
util.Die("couldn't make stdout pipe to nix-editor")
}

return result
}

func RunNixEditorCmds(cmds [][]string) {
for _, cmd := range cmds {
output := util.GetCmdOutput(cmd)

var nixEditorStatus struct {
Status string
Data string
}
err = cmd.Start()
if err != nil {
util.Die("nix-editor error: %s", err)
}

if err := json.Unmarshal(output, &nixEditorStatus); err != nil {
util.Die("unexpected nix-editor output: %s", err)
in := &bytes.Buffer{}
encoder := json.NewEncoder(in)
for _, op := range ops {
err := encoder.Encode(op)
if err != nil {
util.Die("unable to turn op into json: %v error: %s", op, err)
}
if nixEditorStatus.Status != "success" {
util.Die("nix-editor error: %s", nixEditorStatus.Data)
}
_, err = stdin.Write(in.Bytes())
if err != nil {
util.Die("unable to write to nix-editor")
}
stdin.Close()

go func() {
decoder := json.NewDecoder(stdout)
for {
var nixEditorStatus struct {
Status string
Data string
}
err := decoder.Decode(&nixEditorStatus)
if err != nil {
if errors.Is(err, io.EOF) {
break
}
util.Die("unexpected nix-editor output: %s", err)
}
if nixEditorStatus.Status != "success" {
util.Die("nix-editor error: %s", nixEditorStatus.Data)
}
}
// otherwise we have success and don't need to output
// anything
stdout.Close()
}()

err = cmd.Wait()
if err != nil {
util.Die("nix-editor error: %s", err)
}
}
20 changes: 7 additions & 13 deletions internal/nix/nix_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package nix

import (
"os"
"testing"

assert "github.com/stretchr/testify/assert"
Expand All @@ -11,12 +10,12 @@ func TestNixPythonMap(t *testing.T) {
deps := PythonNixDeps("pycairo")

assert.Equal(t,
&ReplitNixAdd{
ReplitNixAdd{
Deps: []string{
"pkgs.pkg-config",
"pkgs.cairo",
},
PythonLibraryDeps: []string{},
PythonLibraryDeps: nil,
},
deps)
}
Expand All @@ -32,18 +31,13 @@ func TestReplitNixAddToNixEditorCmds(t *testing.T) {
},
}

err := os.Setenv("REPL_HOME", "/tmp")
assert.NoError(t, err)
cmds := ReplitNixAddToNixEditorOps(*deps)

cmds := ReplitNixAddToNixEditorCmds(*deps)

expected := [][]string{
[]string{"nix-editor", "--path", "/tmp/replit.nix", "--add", "pkgs.pkg-config"},
[]string{"nix-editor", "--path", "/tmp/replit.nix", "--add", "pkgs.cairo"},
[]string{"nix-editor", "--path", "/tmp/replit.nix", "--dep-type", "python", "--add", "pkgs.lib"},
expected := []NixEditorOp{
{Op: "add", DepType: Regular, Dep: "pkgs.pkg-config"},
{Op: "add", DepType: Regular, Dep: "pkgs.cairo"},
{Op: "add", DepType: Python, Dep: "pkgs.lib"},
}

assert.Equal(t, expected, cmds)
}

// func integration test with python add calling nix adds

0 comments on commit 00b83fd

Please sign in to comment.