func EscapeTilde(path string) (string, error) {
	if !(path == "~" || strings.HasPrefix(path, "~/")) {
		return path, nil
	}
	if _homeDir == "" {
		homeDir, err := homedir.Dir()
		if err != nil {
			return path, err
		}
		if homeDir == "" || homeDir == "/" {
			return path, nil
		}
		_homeDir = homeDir
	}
	if path == "~" {
		return _homeDir, nil
	}
	return filepath.Join(_homeDir, path[2:]), nil
}
e.g. ~/path -> /home/ubuntu/path
returns original path if there was an error
package files
import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"github.com/cortexlabs/cortex/pkg/lib/errors"
	"github.com/cortexlabs/cortex/pkg/lib/prompt"
	"github.com/cortexlabs/cortex/pkg/lib/sets/strset"
	"github.com/cortexlabs/cortex/pkg/lib/slices"
	s "github.com/cortexlabs/cortex/pkg/lib/strings"
	"github.com/denormal/go-gitignore"
	"github.com/mitchellh/go-homedir"
	"github.com/shirou/gopsutil/mem"
	"github.com/xlab/treeprint"
)
var (
	_homeDir string
)
func Open(path string) (*os.File, error) {
	cleanPath, err := EscapeTilde(path)
	if err != nil {
		return nil, err
	}
	file, err := os.Open(cleanPath)
	if err != nil {
		return nil, errors.Wrap(err, errors.Message(ErrorReadFile(path)))
	}
	return file, nil
}
func OpenFile(path string, flag int, perm os.FileMode) (*os.File, error) {
	cleanPath, err := EscapeTilde(path)
	if err != nil {
		return nil, err
	}
	file, err := os.OpenFile(cleanPath, flag, perm)
	if err != nil {
		return nil, errors.Wrap(err, errors.Message(ErrorCreateFile(path)))
	}
	return file, err
}
func Create(path string) (*os.File, error) {
	cleanPath, err := EscapeTilde(path)
	if err != nil {
		return nil, err
	}
	file, err := os.Create(cleanPath)
	if err != nil {
		return nil, errors.Wrap(err, errors.Message(ErrorCreateFile(path)))
	}
	return file, nil
}
func ReadFile(path string) (string, error) {
	fileBytes, err := ReadFileBytes(path)
	if err != nil {
		return "", err
	}
	return string(fileBytes), nil
}
func ReadFileBytes(path string) ([]byte, error) {
	return ReadFileBytesErrPath(path, path)
}
func ReadFileBytesErrPath(path string, errMsgPath string) ([]byte, error) {
	path, err := EscapeTilde(path)
	if err != nil {
		return nil, err
	}
	if err := CheckFileErrPath(path, errMsgPath); err != nil {
		return nil, err
	}
	fileBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, errors.Wrap(err, errors.Message(ErrorReadFile(errMsgPath)))
	}
	return fileBytes, nil
}
func CreateFile(path string) error {
	cleanPath, err := EscapeTilde(path)
	if err != nil {
		return err
	}
	file, err := os.Create(cleanPath)
	if err != nil {
		return errors.Wrap(err, errors.Message(ErrorCreateFile(path)))
	}
	defer file.Close()
	return nil
}
func WriteFileFromReader(reader io.Reader, path string) error {
	cleanPath, err := EscapeTilde(path)
	if err != nil {
		return err
	}
	file, err := os.Create(cleanPath)
	if err != nil {
		return errors.Wrap(err, errors.Message(ErrorCreateFile(path)))
	}
	defer file.Close()
	_, err = io.Copy(file, reader)
	if err != nil {
		return errors.Wrap(err, errors.Message(ErrorCreateFile(path)))
	}
	return nil
}
func WriteFile(data []byte, path string) error {
	cleanPath, err := EscapeTilde(path)
	if err != nil {
		return err
	}
	if err := ioutil.WriteFile(cleanPath, data, 0664); err != nil {
		return errors.Wrap(err, errors.Message(ErrorCreateFile(path)))
	}
	return nil
}
func IsAbsOrTildePrefixed(path string) bool {
	return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "~/")
}