Unverified Commit 6d2d295f authored by Steven Allen's avatar Steven Allen Committed by GitHub

Merge pull request #21 from ipfs/fix/11

serialfile: fix handling of hidden paths on windows
parents 20be69d9 f0180f27
...@@ -40,6 +40,9 @@ func TestWriteTo(t *testing.T) { ...@@ -40,6 +40,9 @@ func TestWriteTo(t *testing.T) {
"5/a": "foobar", "5/a": "foobar",
} }
err = filepath.Walk(path, func(cpath string, info os.FileInfo, err error) error { err = filepath.Walk(path, func(cpath string, info os.FileInfo, err error) error {
if err != nil {
return err
}
rpath, err := filepath.Rel(path, cpath) rpath, err := filepath.Rel(path, cpath)
if err != nil { if err != nil {
return err return err
......
// +build !windows //+build !windows
package files package files
import ( import (
"path/filepath" "os"
"strings"
) )
func IsHidden(name string, f Node) bool { func isHidden(fi os.FileInfo) bool {
fName := filepath.Base(name) fName := fi.Name()
switch fName {
if strings.HasPrefix(fName, ".") && len(fName) > 1 { case "", ".", "..":
return true return false
default:
return fName[0] == '.'
} }
return false
} }
...@@ -3,33 +3,26 @@ ...@@ -3,33 +3,26 @@
package files package files
import ( import (
"path/filepath" "os"
"strings"
windows "golang.org/x/sys/windows" windows "golang.org/x/sys/windows"
) )
func IsHidden(name string, f Node) bool { func isHidden(fi os.FileInfo) bool {
fName := fi.Name()
fName := filepath.Base(name) switch fName {
case "", ".", "..":
return false
}
if strings.HasPrefix(fName, ".") && len(fName) > 1 { if fName[0] == '.' {
return true return true
} }
fi, ok := f.(FileInfo) wi, ok := fi.Sys().(*windows.Win32FileAttributeData)
if !ok { if !ok {
return false return false
} }
p, e := windows.UTF16PtrFromString(fi.AbsPath()) return wi.FileAttributes&windows.FILE_ATTRIBUTE_HIDDEN != 0
if e != nil {
return false
}
attrs, e := windows.GetFileAttributes(p)
if e != nil {
return false
}
return attrs&windows.FILE_ATTRIBUTE_HIDDEN != 0
} }
...@@ -75,7 +75,7 @@ func (it *serialIterator) Next() bool { ...@@ -75,7 +75,7 @@ func (it *serialIterator) Next() bool {
stat := it.files[0] stat := it.files[0]
it.files = it.files[1:] it.files = it.files[1:]
for !it.handleHiddenFiles && strings.HasPrefix(stat.Name(), ".") { for !it.handleHiddenFiles && isHidden(stat) {
if len(it.files) == 0 { if len(it.files) == 0 {
return false return false
} }
......
package files
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
)
func isPathHidden(p string) bool {
return strings.HasPrefix(p, ".") || strings.Contains(p, "/.")
}
func TestSerialFile(t *testing.T) {
t.Run("Hidden", func(t *testing.T) { testSerialFile(t, true) })
t.Run("NotHidden", func(t *testing.T) { testSerialFile(t, false) })
}
func testSerialFile(t *testing.T, hidden bool) {
tmppath, err := ioutil.TempDir("", "files-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmppath)
expected := map[string]string{
"1": "Some text!\n",
"2": "beep",
"3": "",
"4": "boop",
"5": "",
"5/a": "foobar",
".6": "thing",
"7": "",
"7/.foo": "bla",
".8": "",
".8/foo": "bla",
}
for p, c := range expected {
path := filepath.Join(tmppath, p)
if c != "" {
continue
}
if err := os.MkdirAll(path, 0777); err != nil {
t.Fatal(err)
}
}
for p, c := range expected {
path := filepath.Join(tmppath, p)
if c == "" {
continue
}
if err := ioutil.WriteFile(path, []byte(c), 0666); err != nil {
t.Fatal(err)
}
}
stat, err := os.Stat(tmppath)
if err != nil {
t.Fatal(err)
}
sf, err := NewSerialFile(tmppath, hidden, stat)
if err != nil {
t.Fatal(err)
}
defer sf.Close()
rootFound := false
err = Walk(sf, func(path string, nd Node) error {
defer nd.Close()
// root node.
if path == "" {
if rootFound {
return fmt.Errorf("found root twice")
}
if sf != nd {
return fmt.Errorf("wrong root")
}
rootFound = true
return nil
}
if !hidden && isPathHidden(path) {
return fmt.Errorf("found a hidden file")
}
data, ok := expected[path]
if !ok {
return fmt.Errorf("expected something at %q", path)
}
delete(expected, path)
switch nd := nd.(type) {
case *Symlink:
return fmt.Errorf("didn't expect a symlink")
case Directory:
if data != "" {
return fmt.Errorf("expected a directory at %q", path)
}
case File:
actual, err := ioutil.ReadAll(nd)
if err != nil {
return err
}
if string(actual) != data {
return fmt.Errorf("expected %q, got %q", data, string(actual))
}
}
return nil
})
if !rootFound {
t.Fatal("didn't find the root")
}
for p := range expected {
if !hidden && isPathHidden(p) {
continue
}
t.Errorf("missed %q", p)
}
}
package files
import (
"path/filepath"
)
// Walk walks a file tree, like `os.Walk`.
func Walk(nd Node, cb func(fpath string, nd Node) error) error {
var helper func(string, Node) error
helper = func(path string, nd Node) error {
if err := cb(path, nd); err != nil {
return err
}
dir, ok := nd.(Directory)
if !ok {
return nil
}
iter := dir.Entries()
for iter.Next() {
if err := helper(filepath.Join(path, iter.Name()), iter.Node()); err != nil {
return err
}
}
return iter.Err()
}
return helper("", nd)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment