Skip to content

Commit

Permalink
feat: node refactor (#1316)
Browse files Browse the repository at this point in the history
* refactor: node reader interface

* refactor: rewrite Taskfile() as anon recursive func

* chore: NewNodeFromIncludedTaskfile

* chore: changelog
  • Loading branch information
pd93 authored Sep 2, 2023
1 parent b2e6c93 commit afe8a61
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 179 deletions.
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
}
Loading

0 comments on commit afe8a61

Please sign in to comment.