From cbfbe4928fe3e58c37214734a3841b55dee14e85 Mon Sep 17 00:00:00 2001 From: Savil Srivastava <676452+savil@users.noreply.github.com> Date: Fri, 16 Sep 2022 08:53:10 -0700 Subject: [PATCH] [DotNetPlanner] shell and build for C# and F# - rename csharp package to dotnet - Add support for `.fsproj` extension to enable support for F# language. --- cuecfg/cuecfg.go | 12 +++++-- .../dotnet_planner.go} | 31 ++++++++++++++----- planner/languages/dotnet/fsharp_planner.go | 1 + planner/planner.go | 4 +-- testdata/fsharp/fsharp-hello-world/.gitignore | 2 ++ testdata/fsharp/fsharp-hello-world/Program.fs | 12 +++++++ .../fsharp/fsharp-hello-world/devbox.json | 6 ++++ .../fsharp-hello-world.fsproj | 13 ++++++++ testdata/fsharp/fsharp-hello-world/plan.json | 24 ++++++++++++++ 9 files changed, 93 insertions(+), 12 deletions(-) rename planner/languages/{csharp/csharp_planner.go => dotnet/dotnet_planner.go} (86%) create mode 100644 planner/languages/dotnet/fsharp_planner.go create mode 100644 testdata/fsharp/fsharp-hello-world/.gitignore create mode 100644 testdata/fsharp/fsharp-hello-world/Program.fs create mode 100644 testdata/fsharp/fsharp-hello-world/devbox.json create mode 100644 testdata/fsharp/fsharp-hello-world/fsharp-hello-world.fsproj create mode 100644 testdata/fsharp/fsharp-hello-world/plan.json diff --git a/cuecfg/cuecfg.go b/cuecfg/cuecfg.go index 2abf803c1fb..ca10427d56e 100644 --- a/cuecfg/cuecfg.go +++ b/cuecfg/cuecfg.go @@ -26,7 +26,7 @@ func Marshal(valuePtr any, extension string) ([]byte, error) { return marshalYaml(valuePtr) case ".toml": return marshalToml(valuePtr) - case ".xml", ".csproj": + case ".xml": return marshalXML(valuePtr) } return nil, errors.Errorf("Unsupported file format '%s' for config file", extension) @@ -52,7 +52,7 @@ func Unmarshal(data []byte, extension string, valuePtr any) error { return errors.WithStack(err) } return nil - case ".xml", ".csproj": + case ".xml": err := unmarshalXML(data, valuePtr) if err != nil { return errors.WithStack(err) @@ -78,12 +78,18 @@ func InitFile(path string, valuePtr any) (bool, error) { } func ParseFile(path string, valuePtr any) error { + return ParseFileWithExtension(path, filepath.Ext(path), valuePtr) +} + +// ParserFileWithExtension lets the caller override the extension of the `path` filename +// For example, project.csproj files should be treated as having extension .xml +func ParseFileWithExtension(path string, ext string, valuePtr any) error { data, err := os.ReadFile(path) if err != nil { return errors.WithStack(err) } - return Unmarshal(data, filepath.Ext(path), valuePtr) + return Unmarshal(data, ext, valuePtr) } func WriteFile(path string, value any) error { diff --git a/planner/languages/csharp/csharp_planner.go b/planner/languages/dotnet/dotnet_planner.go similarity index 86% rename from planner/languages/csharp/csharp_planner.go rename to planner/languages/dotnet/dotnet_planner.go index 2d2d30e76ac..84898f07201 100644 --- a/planner/languages/csharp/csharp_planner.go +++ b/planner/languages/dotnet/dotnet_planner.go @@ -1,9 +1,10 @@ // Copyright 2022 Jetpack Technologies Inc and contributors. All rights reserved. // Use of this source code is governed by the license in the LICENSE file. -package csharp +package dotnet import ( + "fmt" "strings" "github.com/pkg/errors" @@ -17,13 +18,17 @@ type Project struct { } `xml:"PropertyGroup,omitempty"` } +const CSharpExtension = "csproj" +const FSharpExtension = "fsproj" + +// The .Net Planner supports C# and F# languages. type Planner struct{} // Implements interface Planner (compile-time check) var _ plansdk.Planner = (*Planner)(nil) func (p *Planner) Name() string { - return "csharp.Planner" + return "dotnet.Planner" } func (p *Planner) IsRelevant(srcDir string) bool { @@ -32,7 +37,11 @@ func (p *Planner) IsRelevant(srcDir string) bool { // We should log that an error has occurred. return false } - return a.HasAnyFile("*.csproj") + isRelevant := a.HasAnyFile( + fmt.Sprintf("*.%s", CSharpExtension), + fmt.Sprintf("*.%s", FSharpExtension), + ) + return isRelevant } func (p *Planner) GetPlan(srcDir string) *plansdk.Plan { @@ -40,7 +49,7 @@ func (p *Planner) GetPlan(srcDir string) *plansdk.Plan { if err != nil { // Added this Printf because `devbox shell` was silently swallowing this error. // TODO savil. Have `devbox shell` error out or print it instead. - // fmt.Printf("error in getPlan: %s\n", err) + fmt.Printf("error in getPlan: %+v\n", err) plan = &plansdk.Plan{} plan.WithError(err) } @@ -98,14 +107,22 @@ func project(srcDir string) (*Project, error) { // We should log that an error has occurred. return nil, err } - paths := a.GlobFiles("*.csproj") + paths := a.GlobFiles( + fmt.Sprintf("*.%s", CSharpExtension), + fmt.Sprintf("*.%s", FSharpExtension), + ) if len(paths) < 1 { - return nil, errors.Errorf("expected to find a .csproj file in directory %s", srcDir) + return nil, errors.Errorf( + "expected to find a %s or %s file in directory %s", + CSharpExtension, + FSharpExtension, + srcDir, + ) } projectFilePath := paths[0] proj := &Project{} - err = cuecfg.ParseFile(projectFilePath, proj) + err = cuecfg.ParseFileWithExtension(projectFilePath, ".xml", proj) return proj, err } diff --git a/planner/languages/dotnet/fsharp_planner.go b/planner/languages/dotnet/fsharp_planner.go new file mode 100644 index 00000000000..8983fff1db0 --- /dev/null +++ b/planner/languages/dotnet/fsharp_planner.go @@ -0,0 +1 @@ +package dotnet diff --git a/planner/planner.go b/planner/planner.go index df3635c894e..9f1aa80a0cb 100644 --- a/planner/planner.go +++ b/planner/planner.go @@ -9,9 +9,9 @@ import ( "go.jetpack.io/devbox/planner/languages/clojure" "go.jetpack.io/devbox/planner/languages/cplusplus" "go.jetpack.io/devbox/planner/languages/crystal" - "go.jetpack.io/devbox/planner/languages/csharp" "go.jetpack.io/devbox/planner/languages/dart" "go.jetpack.io/devbox/planner/languages/deno" + "go.jetpack.io/devbox/planner/languages/dotnet" "go.jetpack.io/devbox/planner/languages/elixir" "go.jetpack.io/devbox/planner/languages/erlang" "go.jetpack.io/devbox/planner/languages/fsharp" @@ -41,7 +41,7 @@ var PLANNERS = []plansdk.Planner{ &clojure.Planner{}, &cplusplus.Planner{}, &crystal.Planner{}, - &csharp.Planner{}, + &dotnet.Planner{}, &dart.Planner{}, &deno.Planner{}, &elixir.Planner{}, diff --git a/testdata/fsharp/fsharp-hello-world/.gitignore b/testdata/fsharp/fsharp-hello-world/.gitignore new file mode 100644 index 00000000000..cd42ee34e87 --- /dev/null +++ b/testdata/fsharp/fsharp-hello-world/.gitignore @@ -0,0 +1,2 @@ +bin/ +obj/ diff --git a/testdata/fsharp/fsharp-hello-world/Program.fs b/testdata/fsharp/fsharp-hello-world/Program.fs new file mode 100644 index 00000000000..5a5701951b6 --- /dev/null +++ b/testdata/fsharp/fsharp-hello-world/Program.fs @@ -0,0 +1,12 @@ +// For more information see https://aka.ms/fsharp-console-apps + +[] +let main args = + let dotNetVersion = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription + printfn "Installed version is %A" dotNetVersion + + let expectedVersionPrefix = ".NET 6" + if (not (dotNetVersion.StartsWith(expectedVersionPrefix))) then + raise (System.Exception(sprintf "Expected version %A but got version %A" expectedVersionPrefix dotNetVersion)) + else + 0 diff --git a/testdata/fsharp/fsharp-hello-world/devbox.json b/testdata/fsharp/fsharp-hello-world/devbox.json new file mode 100644 index 00000000000..3352a1b2467 --- /dev/null +++ b/testdata/fsharp/fsharp-hello-world/devbox.json @@ -0,0 +1,6 @@ +{ + "packages": [], + "shell": { + "init_hook": null + } +} \ No newline at end of file diff --git a/testdata/fsharp/fsharp-hello-world/fsharp-hello-world.fsproj b/testdata/fsharp/fsharp-hello-world/fsharp-hello-world.fsproj new file mode 100644 index 00000000000..337d8fce1a1 --- /dev/null +++ b/testdata/fsharp/fsharp-hello-world/fsharp-hello-world.fsproj @@ -0,0 +1,13 @@ + + + + Exe + net6.0 + fsharp_hello_world + + + + + + + diff --git a/testdata/fsharp/fsharp-hello-world/plan.json b/testdata/fsharp/fsharp-hello-world/plan.json new file mode 100644 index 00000000000..5b3a4f5da7e --- /dev/null +++ b/testdata/fsharp/fsharp-hello-world/plan.json @@ -0,0 +1,24 @@ +{ + "dev_packages": [ + "dotnet-sdk" + ], + "runtime_packages": [ + "dotnet-sdk" + ], + "install_stage": { + "command": "" + }, + "build_stage": { + "command": "dotnet publish", + "input_files": [ + "." + ] + }, + "start_stage": { + "command": "dotnet run", + "input_files": [ + "." + ] + }, + "definitions": null +}