Last active
July 6, 2018 09:40
-
-
Save imsodin/b8ec2ec226a0575f7619997b287e6e28 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"fmt" | |
"os" | |
"path/filepath" | |
"runtime" | |
"strings" | |
) | |
const PathSeparator = os.PathSeparator | |
type BasicFilesystem struct { | |
root string | |
rootSymlinkEvaluated string | |
} | |
func newBasicFilesystem(root string) *BasicFilesystem { | |
fmt.Println("newBasicFilesystem start:", root) | |
// The reason it's done like this: | |
// C: -> C:\ -> C:\ (issue that this is trying to fix) | |
// C:\somedir -> C:\somedir\ -> C:\somedir | |
// C:\somedir\ -> C:\somedir\\ -> C:\somedir | |
// This way in the tests, we get away without OS specific separators | |
// in the test configs. | |
root = filepath.Dir(root + string(filepath.Separator)) | |
fmt.Println("newBasicFilesystem windows root hack:", root) | |
// Attempt tilde expansion; leave unchanged in case of error | |
if path, err := ExpandTilde(root); err == nil { | |
fmt.Println("newBasicFilesystem tilde expansion:", path) | |
root = path | |
} else { | |
fmt.Println("newBasicFilesystem tilde expansion failed:", path, err) | |
} | |
// Attempt absolutification; leave unchanged in case of error | |
if !filepath.IsAbs(root) { | |
// Abs() looks like a fairly expensive syscall on Windows, while | |
// IsAbs() is a whole bunch of string mangling. I think IsAbs() may be | |
// somewhat faster in the general case, hence the outer if... | |
if path, err := filepath.Abs(root); err == nil { | |
fmt.Println("newBasicFilesystem absolutification:", path) | |
root = path | |
} else { | |
fmt.Println("newBasicFilesystem absolutification failed:", path, err) | |
} | |
} | |
rootSymlinkEvaluated, err := filepath.EvalSymlinks(root) | |
if err != nil { | |
rootSymlinkEvaluated = root | |
fmt.Println("newBasicFilesystem EvalSymlinks failed:", rootSymlinkEvaluated, err) | |
} else { | |
fmt.Println("newBasicFilesystem EvalSymlinks:", rootSymlinkEvaluated) | |
} | |
return &BasicFilesystem{ | |
root: adjustRoot(root), | |
rootSymlinkEvaluated: adjustRoot(rootSymlinkEvaluated), | |
} | |
} | |
func adjustRoot(root string) string { | |
fmt.Println("adjustRoot in:", root) | |
// Attempt to enable long filename support on Windows. We may still not | |
// have an absolute path here if the previous steps failed. | |
if runtime.GOOS == "windows" { | |
if filepath.IsAbs(root) && !strings.HasPrefix(root, `\\`) { | |
root = `\\?\` + root | |
} | |
return root | |
} | |
// If we're not on Windows, we want the path to end with a slash to | |
// penetrate symlinks. On Windows, paths must not end with a slash. | |
if root[len(root)-1] != filepath.Separator { | |
root = root + string(filepath.Separator) | |
} | |
fmt.Println("adjustRoot result:", root) | |
return root | |
} | |
var errNoHome = errors.New("no home directory found - set $HOME (or the platform equivalent)") | |
func ExpandTilde(path string) (string, error) { | |
if path == "~" { | |
return getHomeDir() | |
} | |
path = filepath.FromSlash(path) | |
if !strings.HasPrefix(path, fmt.Sprintf("~%c", PathSeparator)) { | |
return path, nil | |
} | |
home, err := getHomeDir() | |
if err != nil { | |
return "", err | |
} | |
return filepath.Join(home, path[2:]), nil | |
} | |
func getHomeDir() (string, error) { | |
var home string | |
switch runtime.GOOS { | |
case "windows": | |
home = filepath.Join(os.Getenv("HomeDrive"), os.Getenv("HomePath")) | |
if home == "" { | |
home = os.Getenv("UserProfile") | |
} | |
default: | |
home = os.Getenv("HOME") | |
} | |
if home == "" { | |
return "", errNoHome | |
} | |
return home, nil | |
} | |
func main() { | |
fmt.Println(newBasicFilesystem("/home/piotr/storage/synced/oneplus5/")) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment