Skip to content

Commit

Permalink
Windows root parse fix
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Dominic Della Valle <ddvpublic@gmail.com>
  • Loading branch information
djdv committed Dec 6, 2016
1 parent 4511a4a commit 55c51bd
Showing 1 changed file with 43 additions and 2 deletions.
45 changes: 43 additions & 2 deletions commands/cli/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (

cmds "github.com/ipfs/go-ipfs/commands"
files "github.com/ipfs/go-ipfs/commands/files"

logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
osh "gx/ipfs/QmXuBJ7DR6k3rmUEKtvVMhwjmXDuJgXXPUt4LQXKBMsU93/go-os-helper"
u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util"
)

Expand Down Expand Up @@ -399,8 +401,20 @@ func getArgDef(i int, argDefs []cmds.Argument) *cmds.Argument {

const notRecursiveFmtStr = "'%s' is a directory, use the '-%s' flag to specify directories"
const dirNotSupportedFmtStr = "Invalid path '%s', argument '%s' does not support directories"
const winDriveLetterFmtStr = "%q is a drive letter, not a drive path"

func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (files.File, error) {
// resolve Windows relative dot paths like `X:.\somepath`
if osh.IsWindows() {
if len(fpath) >= 3 && fpath[1:3] == ":." {
var err error
fpath, err = filepath.Abs(fpath)
if err != nil {
return nil, err
}
}
}

if fpath == "." {
cwd, err := os.Getwd()
if err != nil {
Expand All @@ -413,7 +427,7 @@ func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (fi
fpath = cwd
}

fpath = filepath.ToSlash(filepath.Clean(fpath))
fpath = filepath.Clean(fpath)

stat, err := os.Lstat(fpath)
if err != nil {
Expand All @@ -429,7 +443,34 @@ func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (fi
}
}

return files.NewSerialFile(path.Base(fpath), fpath, hidden, stat)
// special cases for Windows drive roots i.e. `X:\` and their long form `\\?\X:\`
// drive path must be preserved as `X:\` (or it's longform) and not converted to `X:`, `X:.`, `\`, or `/` here
if osh.IsWindows() {
switch len(fpath) {
case 3:
// `X:` is cleaned to `X:.` which may not be the expected behaviour by the user, they'll need to provide more specific input
if fpath[1:3] == ":." {
return nil, fmt.Errorf(winDriveLetterFmtStr, fpath[:2])
}
// `X:\` needs to preserve the `\`, path.Base(filepath.ToSlash(fpath)) results in `X:` which is not valid
if fpath[1:3] == ":\\" {
return files.NewSerialFile(fpath, fpath, hidden, stat)
}
case 6:
// `\\?\X:` long prefix form of `X:`, still ambiguous
if fpath[:4] == "\\\\?\\" && fpath[5] == ':' {
return nil, fmt.Errorf(winDriveLetterFmtStr, fpath)
}
case 7:
// `\\?\X:\` long prefix form is translated into short form `X:\`
if fpath[:4] == "\\\\?\\" && fpath[5] == ':' && fpath[6] == '\\' {
fpath = string(fpath[4]) + ":\\"
return files.NewSerialFile(fpath, fpath, hidden, stat)
}
}
}

return files.NewSerialFile(path.Base(filepath.ToSlash(fpath)), fpath, hidden, stat)
}

// Inform the user if a file is waiting on input
Expand Down

0 comments on commit 55c51bd

Please sign in to comment.