Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow overriding ACT-R and CCL versions using an external file #395

Merged
merged 1 commit into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ USAGE:

OPTIONS:
--dev install any dev packages (default: false)
--env string directory where ACT-R, pyactr, and other necessary files are installed (default "./env")
--path value, -p value directory for env files (it will be created if it does not exist) (default: "./env")
```

For basic setup, run `./gactar env setup`
Expand All @@ -203,10 +203,10 @@ Use the `--dev` flag to also install optional developer packages for linting & f
$ ./gactar env setup --dev
```

If you want to change the default environment (`env`), the directory can be specified using the `--env` option:
If you want to change the default environment (`env`), the directory can be specified using the `-path` option:

```
./gactar env setup --env foo
./gactar env setup -path foo
```

**Note:** If you change the default environment, you will need to specify `--env foo` each time you run gactar.
Expand Down
125 changes: 104 additions & 21 deletions cmd/env.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package cmd

import (
"encoding/json"
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"runtime"
"slices"

"github.com/spf13/cobra"

Expand All @@ -19,10 +21,19 @@ import (
)

const (
// ACT-R release version from https://github.com/asmaloney/ACT-R
// JSON file used to override our defaults
SUPPORT_TOOLS_FILE = "install/support-tools.json"

// Default ACT-R repo
ACTR_REPO = "github.com/asmaloney/ACT-R"

// Default ACT-R release version
ACTR_VERSION = "7.27.7"

// Clozure Common Lisp release version from https://github.com/Clozure/ccl
// Default Clozure Common Lisp repo
CCL_REPO = "github.com/Clozure/ccl"

// Default Clozure Common Lisp release version
CCL_VERSION = "1.12.2"
)

Expand All @@ -36,6 +47,11 @@ var (
flagUpdatePython = false
flagUpdatePythonPackages = false
flagUpdateDev = false

// names we allow in the support-tools file
validTools = []string{"ACT-R", "CCL"}

defaultToolInfo = make(toolInfoMap, len(validTools))
)

var envCmd = &cobra.Command{
Expand All @@ -51,7 +67,7 @@ var setupCmd = &cobra.Command{
Use: "setup",
Short: "Setup an environment",
Run: func(cmd *cobra.Command, args []string) {
envPath, err := getVirtualEnvironmentPath(cmd.Flags())
envPath, err := expandPathFlag(cmd.Flags(), "path")
if err != nil {
chalk.PrintErr(err)
return
Expand Down Expand Up @@ -98,8 +114,26 @@ func (e errCCLSystem) Error() string {
return fmt.Sprintf("no CCL compiler available for system %q", e.OSName)
}

// toolInfoList is used to read tool version info from a file
type toolInfoList struct {
List []toolInfo `json:"tool-info"`
}

// toolInfoMap maps a tool name to its info
type toolInfoMap map[string]toolInfo

// toolInfo stores version info about a tool
type toolInfo struct {
Name string `json:"name"`
RepoURL string `json:"repo-url"`
Version string `json:"version"`
}

func init() {
setDefaultToolInfo()

setupCmd.Flags().BoolVar(&flagSetupDev, "dev", false, "install dev packages")
setupCmd.Flags().StringP("path", "p", "./env", "directory for env files (it will be created if it does not exist)")

envCmd.AddCommand(setupCmd)

Expand All @@ -113,6 +147,57 @@ func init() {
rootCmd.AddCommand(envCmd)
}

// setDefaultToolInfo fills in the default tool versions as a fallback in case the external
// file doesn't exist or fails to parse.
func setDefaultToolInfo() {
defaultToolInfo["ACT-R"] = toolInfo{
Name: "ACT-R",
RepoURL: ACTR_REPO,
Version: ACTR_VERSION,
}

defaultToolInfo["CCL"] = toolInfo{
Name: "CCL",
RepoURL: CCL_REPO,
Version: CCL_VERSION,
}
}

func readToolInfo() (toolInfo toolInfoMap, err error) {
file, err := os.ReadFile(SUPPORT_TOOLS_FILE)
if err != nil {
return
}

data := toolInfoList{}

err = json.Unmarshal(file, &data)
if err != nil {
return
}

if len(data.List) == 0 {
chalk.PrintWarningStr(fmt.Sprintf("failed to find version information in %q; using defaults", SUPPORT_TOOLS_FILE))
return defaultToolInfo, err
}

toolInfo = defaultToolInfo

// Get our version from the support-tools file
for _, info := range data.List {
if !slices.Contains(validTools, info.Name) {
chalk.PrintWarningStr(fmt.Sprintf("invalid tool name found in support-tools file: %q", info.Name))
continue
}

tool := toolInfo[info.Name]
tool.Version = info.Version
toolInfo[info.Name] = tool
}

return
}

func runSetup(envPath string, dev bool) (err error) {
fmt.Println("gactar Environment Setup\n---")
fmt.Printf("Setting up an environment: %q\n", envPath)
Expand All @@ -121,8 +206,11 @@ func runSetup(envPath string, dev bool) (err error) {
if filesystem.DirExists(envPath) {
err = fmt.Errorf("cannot set environment path to %q: %w", envPath, errPathExists)
return
} else {
err = nil
}

tools, err := readToolInfo()
if err != nil {
return err
}

// Create the virtual environment directory
Expand All @@ -138,15 +226,13 @@ func runSetup(envPath string, dev bool) (err error) {

err = setupPython(envPath, dev)
if err != nil {
fmt.Println(err.Error())
err = nil
chalk.PrintErr(err)
// Don't return - we can still try to set up the Lisp compiler
}

err = setupLisp()
err = setupLisp(tools)
if err != nil {
fmt.Println(err.Error())
err = nil
return err
}

return
Expand Down Expand Up @@ -214,38 +300,35 @@ func setupPython(envPath string, dev bool) (err error) {
return
}

func setupLisp() (err error) {
func setupLisp(tools toolInfoMap) (err error) {
fmt.Println()
fmt.Println("Setting up Lisp\n---")

// Download vanilla ACT-R
repo := "github.com/asmaloney/ACT-R"
extension := "zip"
archiveFile := fmt.Sprintf("actr-super-slim-v%s.%s", ACTR_VERSION, extension)
actrInfo := tools["ACT-R"]
archiveFile := fmt.Sprintf("actr-super-slim-v%s.zip", actrInfo.Version)

err = downloadGitHubRelease("ACT-R", repo, ACTR_VERSION, archiveFile, "actr")
err = downloadGitHubRelease("ACT-R", actrInfo.RepoURL, actrInfo.Version, archiveFile, "actr")
if err != nil {
return
}

// Download Clozure Common Lisp compiler (CCL)
cclInfo := tools["CCL"]
system := runtime.GOOS
if system != "darwin" && system != "linux" && system != "windows" {
return &errCCLSystem{OSName: system}
}

repo = "github.com/Clozure/ccl"
extension = "tar.gz"
version := CCL_VERSION

extension := "tar.gz"
if system == "windows" {
extension = "zip"
}

dirName := fmt.Sprintf("ccl-%s-%sx86", version, system)
dirName := fmt.Sprintf("ccl-%s-%sx86", cclInfo.Version, system)
archiveFile = fmt.Sprintf("%s.%s", dirName, extension)

err = downloadGitHubRelease("Clozure Common Lisp (ccl)", repo, version, archiveFile, "")
err = downloadGitHubRelease("Clozure Common Lisp (ccl)", cclInfo.RepoURL, cclInfo.Version, archiveFile, "")
if err != nil {
return
}
Expand Down
12 changes: 12 additions & 0 deletions install/support-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"tool-info": [
{
"name": "ACT-R",
"version": "7.27.7"
},
{
"name": "CCL",
"version": "1.12.2"
}
]
}