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

feat: node refactor #1316

Merged
merged 4 commits into from
Sep 2, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Prep work for remote Taskfiles (#1316 by @pd93).

## v3.29.1 - 2023-08-26

- Update to Go 1.21 (bump minimum version to 1.20) (#1302 by @pd93)
Expand All @@ -9,8 +13,8 @@
- Fix bug in usage of special variables like `{{.USER_WORKING_DIR}}` in
combination with `includes` (#1046, #1205, #1250, #1293, #1312, #1274 by
@andarto, #1309 by @andreynering).
- Fix bug on `--status` flag. Running this flag should not have side-effects:
it should not update the checksum on `.task`, only report its status (#1305,
- Fix bug on `--status` flag. Running this flag should not have side-effects: it
should not update the checksum on `.task`, only report its status (#1305,
#1307 by @visciang, #1313 by @andreynering).

## v3.28.0 - 2023-07-24
Expand Down
10 changes: 5 additions & 5 deletions errors/errors_taskfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
// TaskfileNotFoundError is returned when no appropriate Taskfile is found when
// searching the filesystem.
type TaskfileNotFoundError struct {
Dir string
URI string
Walk bool
}

Expand All @@ -16,7 +16,7 @@ func (err TaskfileNotFoundError) Error() string {
if err.Walk {
walkText = " (or any of the parent directories)"
}
return fmt.Sprintf(`task: No Taskfile found in "%s"%s. Use "task --init" to create a new one`, err.Dir, walkText)
return fmt.Sprintf(`task: No Taskfile found at "%s"%s`, err.URI, walkText)
}

func (err TaskfileNotFoundError) Code() int {
Expand All @@ -38,12 +38,12 @@ func (err TaskfileAlreadyExistsError) Code() int {
// TaskfileInvalidError is returned when the Taskfile contains syntax errors or
// cannot be parsed for some reason.
type TaskfileInvalidError struct {
FilePath string
Err error
URI string
Err error
}

func (err TaskfileInvalidError) Error() string {
return fmt.Sprintf("task: Failed to parse %s:\n%v", err.FilePath, err.Err)
return fmt.Sprintf("task: Failed to parse %s:\n%v", err.URI, err.Err)
}

func (err TaskfileInvalidError) Code() int {
Expand Down
10 changes: 6 additions & 4 deletions setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ func (e *Executor) setCurrentDir() error {

func (e *Executor) readTaskfile() error {
var err error
e.Taskfile, e.Dir, err = read.Taskfile(&read.ReaderNode{
e.Taskfile, err = read.Taskfile(&read.FileNode{
Dir: e.Dir,
Entrypoint: e.Entrypoint,
Parent: nil,
Optional: false,
})
return err
if err != nil {
return err
}
e.Dir = filepath.Dir(e.Taskfile.Location)
return nil
}

func (e *Executor) setupFuzzyModel() {
Expand Down
35 changes: 35 additions & 0 deletions taskfile/read/node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package read

import (
"strings"

"github.com/go-task/task/v3/taskfile"
)

type Node interface {
Read() (*taskfile.Taskfile, error)
Parent() Node
Optional() bool
Location() string
}

func NewNodeFromIncludedTaskfile(parent Node, includedTaskfile taskfile.IncludedTaskfile) (Node, error) {
switch getScheme(includedTaskfile.Taskfile) {
// TODO: Add support for other schemes.
// If no other scheme matches, we assume it's a file.
// This also allows users to explicitly set a file:// scheme.
default:
path, err := includedTaskfile.FullTaskfilePath()
if err != nil {
return nil, err
}
return NewFileNode(parent, path, includedTaskfile.Optional)
}
}

func getScheme(uri string) string {
if i := strings.Index(uri, "://"); i != -1 {
return uri[:i]
}
return ""
}
18 changes: 18 additions & 0 deletions taskfile/read/node_base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package read

// BaseNode is a generic node that implements the Parent() and Optional()
// methods of the NodeReader interface. It does not implement the Read() method
// and it designed to be embedded in other node types so that this boilerplate
// code does not need to be repeated.
type BaseNode struct {
parent Node
optional bool
}

func (node *BaseNode) Parent() Node {
return node.parent
}

func (node *BaseNode) Optional() bool {
return node.optional
}
70 changes: 70 additions & 0 deletions taskfile/read/node_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package read

import (
"os"
"path/filepath"

"gopkg.in/yaml.v3"

"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/taskfile"
)

// A FileNode is a node that reads a taskfile from the local filesystem.
type FileNode struct {
BaseNode
Dir string
Entrypoint string
}

func NewFileNode(parent Node, path string, optional bool) (*FileNode, error) {
path, err := exists(path)
if err != nil {
return nil, err
}

return &FileNode{
BaseNode: BaseNode{
parent: parent,
optional: optional,
},
Dir: filepath.Dir(path),
Entrypoint: filepath.Base(path),
}, nil
}

func (node *FileNode) Location() string {
return filepathext.SmartJoin(node.Dir, node.Entrypoint)
}

func (node *FileNode) Read() (*taskfile.Taskfile, error) {
if node.Dir == "" {
d, err := os.Getwd()
if err != nil {
return nil, err
}
node.Dir = d
}

path, err := existsWalk(node.Location())
if err != nil {
return nil, err
}
node.Dir = filepath.Dir(path)
node.Entrypoint = filepath.Base(path)

f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()

var t taskfile.Taskfile
if err := yaml.NewDecoder(f).Decode(&t); err != nil {
return nil, &errors.TaskfileInvalidError{URI: filepathext.TryAbsToRel(path), Err: err}
}

t.Location = path
return &t, nil
}