diff --git a/tools/rbcrun/host.go b/tools/rbcrun/host.go index 1d68d43fb5..7f5e3327c0 100644 --- a/tools/rbcrun/host.go +++ b/tools/rbcrun/host.go @@ -31,11 +31,11 @@ import ( type ExecutionMode int const ( ExecutionModeRbc ExecutionMode = iota - ExecutionModeMake ExecutionMode = iota + ExecutionModeScl ExecutionMode = iota ) const allowExternalEntrypointKey = "allowExternalEntrypoint" -const callerDirKey = "callerDir" +const callingFileKey = "callingFile" const executionModeKey = "executionMode" const shellKey = "shell" @@ -58,7 +58,7 @@ var rbcBuiltins starlark.StringDict = starlark.StringDict{ "rblf_wildcard": starlark.NewBuiltin("rblf_wildcard", wildcard), } -var makeBuiltins starlark.StringDict = starlark.StringDict{ +var sclBuiltins starlark.StringDict = starlark.StringDict{ "struct": starlark.NewBuiltin("struct", starlarkstruct.Make), "json": starlarkjson.Module, } @@ -128,7 +128,8 @@ func loader(thread *starlark.Thread, module string) (starlark.StringDict, error) module = module[:pipePos] } } - modulePath, err := cleanModuleName(module, thread.Local(callerDirKey).(string), allowExternalEntrypoint) + callingFile := thread.Local(callingFileKey).(string) + modulePath, err := cleanModuleName(module, filepath.Dir(callingFile), allowExternalEntrypoint) if err != nil { return nil, err } @@ -150,6 +151,13 @@ func loader(thread *starlark.Thread, module string) (starlark.StringDict, error) // Load or return default if mustLoad { + if strings.HasSuffix(callingFile, ".scl") && !strings.HasSuffix(modulePath, ".scl") { + return nil, fmt.Errorf(".scl files can only load other .scl files: %q loads %q", callingFile, modulePath) + } + // Switch into scl mode from here on + if strings.HasSuffix(modulePath, ".scl") { + mode = ExecutionModeScl + } childThread := &starlark.Thread{Name: "exec " + module, Load: thread.Load} // Cheating for the sake of testing: // propagate starlarktest's Reporter key, otherwise testing @@ -161,14 +169,14 @@ func loader(thread *starlark.Thread, module string) (starlark.StringDict, error) // Only the entrypoint starlark file allows external loads. childThread.SetLocal(allowExternalEntrypointKey, false) - childThread.SetLocal(callerDirKey, filepath.Dir(modulePath)) + childThread.SetLocal(callingFileKey, modulePath) childThread.SetLocal(executionModeKey, mode) childThread.SetLocal(shellKey, thread.Local(shellKey)) if mode == ExecutionModeRbc { globals, err := starlark.ExecFile(childThread, modulePath, nil, rbcBuiltins) e = &modentry{globals, err} - } else if mode == ExecutionModeMake { - globals, err := starlark.ExecFile(childThread, modulePath, nil, makeBuiltins) + } else if mode == ExecutionModeScl { + globals, err := starlark.ExecFile(childThread, modulePath, nil, sclBuiltins) e = &modentry{globals, err} } else { return nil, fmt.Errorf("unknown executionMode %d", mode) @@ -338,7 +346,7 @@ func Run(filename string, src interface{}, mode ExecutionMode, allowExternalEntr if mode == ExecutionModeRbc { // In rbc mode, rblf_log is used to print to stderr fmt.Println(msg) - } else if mode == ExecutionModeMake { + } else if mode == ExecutionModeScl { fmt.Fprintln(os.Stderr, msg) } }, @@ -365,13 +373,13 @@ func Run(filename string, src interface{}, mode ExecutionMode, allowExternalEntr var results starlark.StringDict mainThread.SetLocal(allowExternalEntrypointKey, allowExternalEntrypoint) - mainThread.SetLocal(callerDirKey, filepath.Dir(filename)) + mainThread.SetLocal(callingFileKey, filename) mainThread.SetLocal(executionModeKey, mode) mainThread.SetLocal(shellKey, shellPath) if mode == ExecutionModeRbc { results, err = starlark.ExecFile(mainThread, filename, src, rbcBuiltins) - } else if mode == ExecutionModeMake { - results, err = starlark.ExecFile(mainThread, filename, src, makeBuiltins) + } else if mode == ExecutionModeScl { + results, err = starlark.ExecFile(mainThread, filename, src, sclBuiltins) } else { return results, nil, fmt.Errorf("unknown executionMode %d", mode) } diff --git a/tools/rbcrun/host_test.go b/tools/rbcrun/host_test.go index 10ce55ec2f..468a620b51 100644 --- a/tools/rbcrun/host_test.go +++ b/tools/rbcrun/host_test.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "testing" "go.starlark.net/resolve" @@ -126,7 +127,7 @@ func TestLoad(t *testing.T) { t.Fatal(err) } thread.SetLocal(allowExternalEntrypointKey, false) - thread.SetLocal(callerDirKey, dir) + thread.SetLocal(callingFileKey, "testdata/load.star") thread.SetLocal(executionModeKey, ExecutionModeRbc) if _, err := starlark.ExecFile(thread, "testdata/load.star", nil, rbcBuiltins); err != nil { if err, ok := err.(*starlark.EvalError); ok { @@ -136,6 +137,55 @@ func TestLoad(t *testing.T) { } } +func TestBzlLoadsScl(t *testing.T) { + moduleCache = make(map[string]*modentry) + dir := dataDir() + if err := os.Chdir(filepath.Dir(dir)); err != nil { + t.Fatal(err) + } + vars, _, err := Run("testdata/bzl_loads_scl.bzl", nil, ExecutionModeScl, false) + if err != nil { + t.Fatal(err) + } + if val, ok := vars["foo"]; !ok { + t.Fatalf("Failed to load foo variable") + } else if val.(starlark.String) != "bar" { + t.Fatalf("Expected \"bar\", got %q", val) + } +} + +func TestNonEntrypointBzlLoadsScl(t *testing.T) { + moduleCache = make(map[string]*modentry) + dir := dataDir() + if err := os.Chdir(filepath.Dir(dir)); err != nil { + t.Fatal(err) + } + vars, _, err := Run("testdata/bzl_loads_scl_2.bzl", nil, ExecutionModeScl, false) + if err != nil { + t.Fatal(err) + } + if val, ok := vars["foo"]; !ok { + t.Fatalf("Failed to load foo variable") + } else if val.(starlark.String) != "bar" { + t.Fatalf("Expected \"bar\", got %q", val) + } +} + +func TestSclLoadsBzl(t *testing.T) { + moduleCache = make(map[string]*modentry) + dir := dataDir() + if err := os.Chdir(filepath.Dir(dir)); err != nil { + t.Fatal(err) + } + _, _, err := Run("testdata/scl_incorrectly_loads_bzl.scl", nil, ExecutionModeScl, false) + if err == nil { + t.Fatal("Expected failure") + } + if !strings.Contains(err.Error(), ".scl files can only load other .scl files") { + t.Fatalf("Expected error to contain \".scl files can only load other .scl files\": %q", err.Error()) + } +} + func TestShell(t *testing.T) { exerciseStarlarkTestFile(t, "testdata/shell.star") } diff --git a/tools/rbcrun/rbcrun/rbcrun.go b/tools/rbcrun/rbcrun/rbcrun.go index a15b867b60..8c372c71d3 100644 --- a/tools/rbcrun/rbcrun/rbcrun.go +++ b/tools/rbcrun/rbcrun/rbcrun.go @@ -55,13 +55,13 @@ func getMode() rbcrun.ExecutionMode { case "rbc": return rbcrun.ExecutionModeRbc case "make": - return rbcrun.ExecutionModeMake + return rbcrun.ExecutionModeScl case "": quit("-mode flag is required.") default: quit("Unknown -mode value %q, expected 1 of \"rbc\", \"make\"", *modeFlag) } - return rbcrun.ExecutionModeMake + return rbcrun.ExecutionModeScl } var makeStringReplacer = strings.NewReplacer("#", "\\#", "$", "$$") @@ -175,7 +175,7 @@ func main() { quit("%s\n", err) } } - if mode == rbcrun.ExecutionModeMake { + if mode == rbcrun.ExecutionModeScl { if err := printVarsInMakeFormat(variables); err != nil { quit("%s\n", err) } diff --git a/tools/rbcrun/testdata/bzl_loads_scl.bzl b/tools/rbcrun/testdata/bzl_loads_scl.bzl new file mode 100644 index 0000000000..e8deca3d9c --- /dev/null +++ b/tools/rbcrun/testdata/bzl_loads_scl.bzl @@ -0,0 +1,3 @@ +load(":test_scl.scl", _foo = "foo") + +foo = _foo diff --git a/tools/rbcrun/testdata/bzl_loads_scl_2.bzl b/tools/rbcrun/testdata/bzl_loads_scl_2.bzl new file mode 100644 index 0000000000..9a680edc03 --- /dev/null +++ b/tools/rbcrun/testdata/bzl_loads_scl_2.bzl @@ -0,0 +1,3 @@ +load(":bzl_loads_scl.bzl", _foo = "foo") + +foo = _foo diff --git a/tools/rbcrun/testdata/scl_incorrectly_loads_bzl.scl b/tools/rbcrun/testdata/scl_incorrectly_loads_bzl.scl new file mode 100644 index 0000000000..9a680edc03 --- /dev/null +++ b/tools/rbcrun/testdata/scl_incorrectly_loads_bzl.scl @@ -0,0 +1,3 @@ +load(":bzl_loads_scl.bzl", _foo = "foo") + +foo = _foo diff --git a/tools/rbcrun/testdata/test_scl.scl b/tools/rbcrun/testdata/test_scl.scl new file mode 100644 index 0000000000..6360ccb715 --- /dev/null +++ b/tools/rbcrun/testdata/test_scl.scl @@ -0,0 +1,2 @@ + +foo = "bar"