diff options
Diffstat (limited to 'cli/internal/fs/path.go')
| -rw-r--r-- | cli/internal/fs/path.go | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/cli/internal/fs/path.go b/cli/internal/fs/path.go new file mode 100644 index 0000000..2023d69 --- /dev/null +++ b/cli/internal/fs/path.go @@ -0,0 +1,113 @@ +package fs + +import ( + "fmt" + iofs "io/fs" + "os" + "path/filepath" + "reflect" + + "github.com/adrg/xdg" + "github.com/vercel/turbo/cli/internal/turbopath" +) + +// CheckedToAbsoluteSystemPath inspects a string and determines if it is an absolute path. +func CheckedToAbsoluteSystemPath(s string) (turbopath.AbsoluteSystemPath, error) { + if filepath.IsAbs(s) { + return turbopath.AbsoluteSystemPath(s), nil + } + return "", fmt.Errorf("%v is not an absolute path", s) +} + +// ResolveUnknownPath returns unknown if it is an absolute path, otherwise, it +// assumes unknown is a path relative to the given root. +func ResolveUnknownPath(root turbopath.AbsoluteSystemPath, unknown string) turbopath.AbsoluteSystemPath { + if filepath.IsAbs(unknown) { + return turbopath.AbsoluteSystemPath(unknown) + } + return root.UntypedJoin(unknown) +} + +// UnsafeToAbsoluteSystemPath directly converts a string to an AbsoluteSystemPath +func UnsafeToAbsoluteSystemPath(s string) turbopath.AbsoluteSystemPath { + return turbopath.AbsoluteSystemPath(s) +} + +// UnsafeToAnchoredSystemPath directly converts a string to an AbsoluteSystemPath +func UnsafeToAnchoredSystemPath(s string) turbopath.AnchoredSystemPath { + return turbopath.AnchoredSystemPath(s) +} + +// AbsoluteSystemPathFromUpstream is used to mark return values from APIs that we +// expect to give us absolute paths. No checking is performed. +// Prefer to use this over a cast to maintain the search-ability of interfaces +// into and out of the turbopath.AbsoluteSystemPath type. +func AbsoluteSystemPathFromUpstream(s string) turbopath.AbsoluteSystemPath { + return turbopath.AbsoluteSystemPath(s) +} + +// GetCwd returns the calculated working directory after traversing symlinks. +func GetCwd(cwdRaw string) (turbopath.AbsoluteSystemPath, error) { + if cwdRaw == "" { + var err error + cwdRaw, err = os.Getwd() + if err != nil { + return "", err + } + } + // We evaluate symlinks here because the package managers + // we support do the same. + cwdRaw, err := filepath.EvalSymlinks(cwdRaw) + if err != nil { + return "", fmt.Errorf("evaluating symlinks in cwd: %w", err) + } + cwd, err := CheckedToAbsoluteSystemPath(cwdRaw) + if err != nil { + return "", fmt.Errorf("cwd is not an absolute path %v: %v", cwdRaw, err) + } + return cwd, nil +} + +// GetVolumeRoot returns the root directory given an absolute path. +func GetVolumeRoot(absolutePath string) string { + return filepath.VolumeName(absolutePath) + string(os.PathSeparator) +} + +// CreateDirFSAtRoot creates an `os.dirFS` instance at the root of the +// volume containing the specified path. +func CreateDirFSAtRoot(absolutePath string) iofs.FS { + return os.DirFS(GetVolumeRoot(absolutePath)) +} + +// GetDirFSRootPath returns the root path of a os.dirFS. +func GetDirFSRootPath(fsys iofs.FS) string { + // We can't typecheck fsys to enforce using an `os.dirFS` because the + // type isn't exported from `os`. So instead, reflection. 🤷♂️ + + fsysType := reflect.TypeOf(fsys).Name() + if fsysType != "dirFS" { + // This is not a user error, fail fast + panic("GetDirFSRootPath must receive an os.dirFS") + } + + // The underlying type is a string; this is the original path passed in. + return reflect.ValueOf(fsys).String() +} + +// IofsRelativePath calculates a `os.dirFS`-friendly path from an absolute system path. +func IofsRelativePath(fsysRoot string, absolutePath string) (string, error) { + return filepath.Rel(fsysRoot, absolutePath) +} + +// TempDir returns the absolute path of a directory with the given name +// under the system's default temp directory location +func TempDir(subDir string) turbopath.AbsoluteSystemPath { + return turbopath.AbsoluteSystemPath(os.TempDir()).UntypedJoin(subDir) +} + +// GetUserConfigDir returns the platform-specific common location +// for configuration files that belong to a user. +func GetUserConfigDir() turbopath.AbsoluteSystemPath { + configHome := AbsoluteSystemPathFromUpstream(xdg.ConfigHome) + return configHome.UntypedJoin("turborepo") +} |
