node.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package taskfile
  2. import (
  3. "context"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "time"
  8. giturls "github.com/whilp/git-urls"
  9. "github.com/go-task/task/v3/errors"
  10. "github.com/go-task/task/v3/internal/experiments"
  11. "github.com/go-task/task/v3/internal/logger"
  12. )
  13. type Node interface {
  14. Read(ctx context.Context) ([]byte, error)
  15. Parent() Node
  16. Location() string
  17. Dir() string
  18. Remote() bool
  19. ResolveEntrypoint(entrypoint string) (string, error)
  20. ResolveDir(dir string) (string, error)
  21. FilenameAndLastDir() (string, string)
  22. }
  23. func NewRootNode(
  24. l *logger.Logger,
  25. entrypoint string,
  26. dir string,
  27. insecure bool,
  28. timeout time.Duration,
  29. ) (Node, error) {
  30. dir = getDefaultDir(entrypoint, dir)
  31. // If the entrypoint is "-", we read from stdin
  32. if entrypoint == "-" {
  33. return NewStdinNode(dir)
  34. }
  35. return NewNode(l, entrypoint, dir, insecure, timeout)
  36. }
  37. func NewNode(
  38. l *logger.Logger,
  39. entrypoint string,
  40. dir string,
  41. insecure bool,
  42. timeout time.Duration,
  43. opts ...NodeOption,
  44. ) (Node, error) {
  45. var node Node
  46. var err error
  47. scheme, err := getScheme(entrypoint)
  48. if err != nil {
  49. return nil, err
  50. }
  51. switch scheme {
  52. case "git":
  53. node, err = NewGitNode(entrypoint, dir, insecure, opts...)
  54. case "http", "https":
  55. node, err = NewHTTPNode(l, entrypoint, dir, insecure, timeout, opts...)
  56. default:
  57. node, err = NewFileNode(l, entrypoint, dir, opts...)
  58. }
  59. if node.Remote() && !experiments.RemoteTaskfiles.Enabled {
  60. return nil, errors.New("task: Remote taskfiles are not enabled. You can read more about this experiment and how to enable it at https://taskfile.dev/experiments/remote-taskfiles")
  61. }
  62. return node, err
  63. }
  64. func getScheme(uri string) (string, error) {
  65. u, err := giturls.Parse(uri)
  66. if u == nil {
  67. return "", err
  68. }
  69. if strings.HasSuffix(strings.Split(u.Path, "//")[0], ".git") && (u.Scheme == "git" || u.Scheme == "ssh" || u.Scheme == "https" || u.Scheme == "http") {
  70. return "git", nil
  71. }
  72. if i := strings.Index(uri, "://"); i != -1 {
  73. return uri[:i], nil
  74. }
  75. return "", nil
  76. }
  77. func getDefaultDir(entrypoint, dir string) string {
  78. // If the entrypoint and dir are empty, we default the directory to the current working directory
  79. if dir == "" {
  80. if entrypoint == "" {
  81. wd, err := os.Getwd()
  82. if err != nil {
  83. return ""
  84. }
  85. dir = wd
  86. }
  87. return dir
  88. }
  89. // If the directory is set, ensure it is an absolute path
  90. var err error
  91. dir, err = filepath.Abs(dir)
  92. if err != nil {
  93. return ""
  94. }
  95. return dir
  96. }