zephinzer/dev

View on GitHub
pkg/utils/paths.go

Summary

Maintainability
A
40 mins
Test Coverage
C
76%
package utils

import (
    "fmt"
    "os"
    "path"
    "strings"
)

type PathType string

func (pt PathType) String() string {
    switch strings.ToLower(string(pt)) {
    case "f":
        fallthrough
    case "file":
        return "file"
    case "d":
        fallthrough
    case "dir":
        fallthrough
    case "directory":
        fallthrough
    case "folder":
        return "directory"
    }
    return "any"
}

func IsPathType(pathInfo os.FileInfo, pathType PathType) bool {
    switch pathType.String() {
    case "file":
        return !pathInfo.IsDir()
    case "directory":
        return pathInfo.IsDir()
    case "any":
        return true
    }
    return false
}

func PathExists(asType PathType, pathFragments ...string) (bool, error) {
    fullPath := path.Join(pathFragments...)

    pathInfo, statError := os.Stat(fullPath)
    if statError != nil {
        if os.IsNotExist(statError) {
            return false, nil
        }
        return false, fmt.Errorf("failed to get status of path '%s': %s", fullPath, statError)
    }

    return IsPathType(pathInfo, asType), nil
}

func ResolvePath(relativePathFragments ...string) (string, error) {
    fullPath := path.Join(relativePathFragments...)
    if len(fullPath) == 0 {
        fullPath = "."
    }

    // do home path resolution
    if fullPath[0] == '~' {
        userHomeDir, getUserHomeDirError := os.UserHomeDir()
        if getUserHomeDirError != nil {
            return "", fmt.Errorf("failed to resolve the home directory: %s", getUserHomeDirError)
        }
        fullPath = strings.Replace(fullPath, "~", userHomeDir, 1)
    }

    // resolve symlink if it is one
    fileInfo, lstatError := os.Lstat(fullPath)
    if lstatError != nil {
        if !os.IsNotExist(lstatError) {
            return "", fmt.Errorf("failed to stat file at '%s': %s", fullPath, lstatError)
        }
    }
    if fileInfo != nil && fileInfo.Mode()&os.ModeSymlink != 0 {
        resolvedSymlinkPath, _ := os.Readlink(fullPath)
        if len(resolvedSymlinkPath) > 0 {
            return ResolvePath(resolvedSymlinkPath)
        }
    }

    if path.IsAbs(fullPath) {
        return fullPath, nil
    }

    currentWorkingDir, getWdError := os.Getwd()
    if getWdError != nil {
        return "", fmt.Errorf("failed to get working directory: %s", getWdError)
    }
    fullPath = path.Join(currentWorkingDir, fullPath)

    return fullPath, nil
}