From 61b0ca48c5880db1039a410aa57420a8620a8c75 Mon Sep 17 00:00:00 2001 From: Timothy Rule <34501912+trulede@users.noreply.github.com> Date: Thu, 29 Jan 2026 20:28:56 +0100 Subject: [PATCH] Correct import directory resolution for nested imports. --- taskfile/node_file.go | 43 +++++++++++++++++------------------------- taskfile/node_git.go | 22 ++++++++++----------- taskfile/node_http.go | 26 ++++++++++--------------- taskfile/node_stdin.go | 32 ++++++++++++++----------------- 4 files changed, 51 insertions(+), 72 deletions(-) diff --git a/taskfile/node_file.go b/taskfile/node_file.go index bbfb28575e..91f3f56cd4 100644 --- a/taskfile/node_file.go +++ b/taskfile/node_file.go @@ -18,7 +18,7 @@ type FileNode struct { } func NewFileNode(entrypoint, dir string, opts ...NodeOption) (*FileNode, error) { - // Find the entrypoint file + // Find the entrypoint file. resolvedEntrypoint, err := fsext.Search(entrypoint, dir, DefaultTaskfiles) if err != nil { if errors.Is(err, os.ErrNotExist) { @@ -27,7 +27,7 @@ func NewFileNode(entrypoint, dir string, opts ...NodeOption) (*FileNode, error) return nil, err } - // Resolve the directory + // Resolve the directory. resolvedDir, err := fsext.ResolveDir(entrypoint, resolvedEntrypoint, dir) if err != nil { return nil, err @@ -53,38 +53,29 @@ func (node *FileNode) Read() ([]byte, error) { } func (node *FileNode) ResolveEntrypoint(entrypoint string) (string, error) { - // If the file is remote, we don't need to resolve the path + // Resolve to entrypoint without adjustment. if isRemoteEntrypoint(entrypoint) { return entrypoint, nil } - - path, err := execext.ExpandLiteral(entrypoint) + // Resolve relative to this nodes Taskfile location, or absolute. + entrypoint, err := execext.ExpandLiteral(entrypoint) if err != nil { return "", err } - - if filepathext.IsAbs(path) { - return path, nil - } - - // NOTE: Uses the directory of the entrypoint (Taskfile), not the current working directory - // This means that files are included relative to one another - entrypointDir := filepath.Dir(node.entrypoint) - return filepathext.SmartJoin(entrypointDir, path), nil + dir := filepath.Dir(node.Location()) + return filepathext.SmartJoin(dir, entrypoint), nil } func (node *FileNode) ResolveDir(dir string) (string, error) { - path, err := execext.ExpandLiteral(dir) - if err != nil { - return "", err - } - - if filepathext.IsAbs(path) { - return path, nil + if len(dir) == 0 { + // Resolve to the current node.Dir(). + return node.Dir(), nil + } else { + // Resolve include.Dir, relative to this node.Dir(), or absolute. + dir, err := execext.ExpandLiteral(dir) + if err != nil { + return "", err + } + return filepathext.SmartJoin(node.Dir(), dir), nil } - - // NOTE: Uses the directory of the entrypoint (Taskfile), not the current working directory - // This means that files are included relative to one another - entrypointDir := filepath.Dir(node.entrypoint) - return filepathext.SmartJoin(entrypointDir, path), nil } diff --git a/taskfile/node_git.go b/taskfile/node_git.go index 62d429fe3d..426b68c184 100644 --- a/taskfile/node_git.go +++ b/taskfile/node_git.go @@ -200,19 +200,17 @@ func (node *GitNode) ResolveEntrypoint(entrypoint string) (string, error) { } func (node *GitNode) ResolveDir(dir string) (string, error) { - path, err := execext.ExpandLiteral(dir) - if err != nil { - return "", err - } - - if filepathext.IsAbs(path) { - return path, nil + if len(dir) == 0 { + // Resolve to the current node.Dir(). + return node.Dir(), nil + } else { + // Resolve include.Dir, relative to this node.Dir(), or absolute. + dir, err := execext.ExpandLiteral(dir) + if err != nil { + return "", err + } + return filepathext.SmartJoin(node.Dir(), dir), nil } - - // NOTE: Uses the directory of the entrypoint (Taskfile), not the current working directory - // This means that files are included relative to one another - entrypointDir := filepath.Dir(node.Dir()) - return filepathext.SmartJoin(entrypointDir, path), nil } func (node *GitNode) CacheKey() string { diff --git a/taskfile/node_http.go b/taskfile/node_http.go index 3db520d41f..a76d0ae28e 100644 --- a/taskfile/node_http.go +++ b/taskfile/node_http.go @@ -91,23 +91,17 @@ func (node *HTTPNode) ResolveEntrypoint(entrypoint string) (string, error) { } func (node *HTTPNode) ResolveDir(dir string) (string, error) { - path, err := execext.ExpandLiteral(dir) - if err != nil { - return "", err - } - - if filepathext.IsAbs(path) { - return path, nil - } - - // NOTE: Uses the directory of the entrypoint (Taskfile), not the current working directory - // This means that files are included relative to one another - parent := node.Dir() - if node.Parent() != nil { - parent = node.Parent().Dir() + if len(dir) == 0 { + // Resolve to the current node.Dir(). + return node.Dir(), nil + } else { + // Resolve include.Dir, relative to this node.Dir(), or absolute. + dir, err := execext.ExpandLiteral(dir) + if err != nil { + return "", err + } + return filepathext.SmartJoin(node.Dir(), dir), nil } - - return filepathext.SmartJoin(parent, path), nil } func (node *HTTPNode) CacheKey() string { diff --git a/taskfile/node_stdin.go b/taskfile/node_stdin.go index e072a0a279..4502d91b3a 100644 --- a/taskfile/node_stdin.go +++ b/taskfile/node_stdin.go @@ -41,32 +41,28 @@ func (node *StdinNode) Read() ([]byte, error) { } func (node *StdinNode) ResolveEntrypoint(entrypoint string) (string, error) { - // If the file is remote, we don't need to resolve the path + // Resolve to entrypoint without adjustment. if isRemoteEntrypoint(entrypoint) { return entrypoint, nil } - - path, err := execext.ExpandLiteral(entrypoint) + // Resolve relative to this node.Dir() (i.e. the root node), or absolute. + entrypoint, err := execext.ExpandLiteral(entrypoint) if err != nil { return "", err } - - if filepathext.IsAbs(path) { - return path, nil - } - - return filepathext.SmartJoin(node.Dir(), path), nil + return filepathext.SmartJoin(node.Dir(), entrypoint), nil } func (node *StdinNode) ResolveDir(dir string) (string, error) { - path, err := execext.ExpandLiteral(dir) - if err != nil { - return "", err - } - - if filepathext.IsAbs(path) { - return path, nil + if len(dir) == 0 { + // Resolve to the current node.Dir(). + return node.Dir(), nil + } else { + // Resolve include.Dir, relative to this node.Dir(), or absolute. + dir, err := execext.ExpandLiteral(dir) + if err != nil { + return "", err + } + return filepathext.SmartJoin(node.Dir(), dir), nil } - - return filepathext.SmartJoin(node.Dir(), path), nil }