diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 55c6803..29d97fb 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,14 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the -// README at: https://github.com/devcontainers/templates/tree/main/src/go { - "name": "Go", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "name": "Espresso", "image": "mcr.microsoft.com/devcontainers/go:1-1.22-bookworm", - // Features to add to the dev container. More info: https://containers.dev/features. - "features": {}, + "features": { + "ghcr.io/devcontainers/features/docker-in-docker": "latest", + "ghcr.io/devcontainers/features/java": { + "jdkDistro": "amzn", + "version": "21" + } + }, "remoteEnv": { "ESPRESSO_DEBUG": "1" - }, - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "curl -s 'https://get.sdkman.io' | bash && source ~/.bashrc" - // Configure tool-specific properties. - // "customizations": {}, - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" + } } \ No newline at end of file diff --git a/.devcontainer/dockerfile b/.devcontainer/dockerfile new file mode 100644 index 0000000..72ea916 --- /dev/null +++ b/.devcontainer/dockerfile @@ -0,0 +1,4 @@ +FROM mcr.microsoft.com/devcontainers/go:1-1.22-bookworm AS builder + +# upgrade the container +RUN apt-get update && apt-get upgrade -y \ No newline at end of file diff --git a/project/build.go b/project/build.go new file mode 100644 index 0000000..7dac6f1 --- /dev/null +++ b/project/build.go @@ -0,0 +1 @@ +package project diff --git a/project/command.go b/project/command.go index d74bc3b..8fd8fef 100644 --- a/project/command.go +++ b/project/command.go @@ -19,7 +19,18 @@ func AssembleCommandHierarchy() *cobra.Command { Short: "Build the project.", Aliases: []string{"b"}, Run: func(cmd *cobra.Command, args []string) { - println("TODO") + // get the config + cfg, err := GetConfig() + if err != nil { + fmt.Printf("An error occurred while reading the config: %s\n", err) + } + + // discover source files + files, err := DiscoverSourceFiles(cfg) + if err != nil { + fmt.Printf("An error occurred while discovering source files: %s\n", err) + } + fmt.Printf("Discovered %d source file(s)\n", len(files)) }, } root.AddCommand(build) @@ -63,6 +74,9 @@ func AssembleCommandHierarchy() *cobra.Command { Toolchain: Toolchain{ Path: *javaHome, }, + Dependencies: Dependencies{ + Repositories: []Registry{{Url: "https://github.com/Kerosene-Labs/espresso-registry/archive/refs/heads/main.zip"}}, + }, } // write some example code diff --git a/project/discover.go b/project/discover.go new file mode 100644 index 0000000..72842ce --- /dev/null +++ b/project/discover.go @@ -0,0 +1,53 @@ +package project + +import ( + "io/fs" + "os" + "path/filepath" + "strings" +) + +// SourceFIle represents a .java source file on the filesystem +type SourceFile struct { + Path string + Content string +} + +// readSourceFile reads the file at the given path, or returns an error +func readSourceFile(path string) (*SourceFile, error) { + return nil, nil +} + +// IntrospectSourceFiles iterates over the project's base package looking for .java files +// TODO: make this a goroutine? +func DiscoverSourceFiles(cfg *ProjectConfig) ([]SourceFile, error) { + // get the source path + srcPath, err := GetSourcePath(cfg) + if err != nil { + return nil, err + } + + // iterate recursively over child directories + var files []SourceFile = []SourceFile{} + err = filepath.Walk(*srcPath, func(path string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && strings.HasSuffix(info.Name(), ".java") { + text, err := os.ReadFile(path) + if err != nil { + return err + } + files = append(files, SourceFile{ + Path: path, + Content: string(text), + }) + } + return nil + }) + if err != nil { + return nil, err + } + + return files, nil +} diff --git a/project/fs.go b/project/fs.go index 671c2d6..4c0969c 100644 --- a/project/fs.go +++ b/project/fs.go @@ -46,3 +46,19 @@ func GetConfigPath() (*string, error) { return &path, nil } } + +// GetBuildPath gets the absolute path to the build directory +func GetBuildPath(cfg *ProjectConfig) (*string, error) { + wd, err := os.Getwd() + if err != nil { + return nil, err + } + path := wd + + if IsDebugMode() { + path += "/ESPRESSO_DEBUG" + } + + path += "/build" + return &path, nil +} diff --git a/project/handler.go b/project/handler.go index 126f195..c1b6a31 100644 --- a/project/handler.go +++ b/project/handler.go @@ -7,6 +7,24 @@ import ( "gopkg.in/yaml.v3" ) +// Dependency represents a particular dependency +type Dependency struct { + GroupID string `yaml:"groupId"` + ArtifactID string `yaml:"artifactId"` + Version string `yaml:"version"` +} + +// Registry represents a particular repository +type Registry struct { + Url string `yaml:"url"` +} + +// Dependencies represents dependency management configuration +type Dependencies struct { + Repositories []Registry `yaml:"registries"` + Dependencies []Dependency `yaml:"uses"` +} + // Toolchain represents the toolchain on the system type Toolchain struct { Path string `yaml:"path"` @@ -20,12 +38,23 @@ type Version struct { Hotfix *string `yaml:"hotfix"` } -// Project represents an Espresso project +// ProjectConfig represents an Espresso project type ProjectConfig struct { - Name string `yaml:"name"` - Version Version `yaml:"version"` - BasePackage string `yaml:"base_package"` - Toolchain Toolchain `yaml:"toolchain"` + Name string `yaml:"name"` + Version Version `yaml:"version"` + BasePackage string `yaml:"basePackage"` + Toolchain Toolchain `yaml:"toolchain"` + Dependencies Dependencies `yaml:"dependencies"` +} + +// UnmarshalConfig marshals the given ProjectConfig to yml +func UnmarshalConfig(cfgYml string) (*ProjectConfig, error) { + var cfg ProjectConfig + err := yaml.Unmarshal([]byte(cfgYml), &cfg) + if err != nil { + return nil, err + } + return &cfg, nil } // MarshalConfig marshals the given ProjectConfig to yml @@ -38,6 +67,28 @@ func MarshalConfig(cfg *ProjectConfig) (*string, error) { return &resp, nil } +// GetConfig reads the config from the filesystem and returns a pointer to a ProjectConfig, or an error +func GetConfig() (*ProjectConfig, error) { + // get the config path for this context + path, err := GetConfigPath() + if err != nil { + return nil, err + } + + // read the file + file, err := os.ReadFile(*path) + if err != nil { + return nil, err + } + + // unmarshal into a cfg struct + cfg, err := UnmarshalConfig(string(file)) + if err != nil { + return nil, err + } + return cfg, nil +} + // ConfigExists gets if a config exists at the current directory func ConfigExists() (*bool, error) { configPath, err := GetConfigPath() diff --git a/toolchain/handler.go b/toolchain/handler.go deleted file mode 100644 index 4b74680..0000000 --- a/toolchain/handler.go +++ /dev/null @@ -1 +0,0 @@ -package toolchain