Skip to content

Commit 7c25c21

Browse files
authored
Merge pull request #15 from LandonTClipp/stat
Breaking out stat into separate functions
2 parents d2cf200 + cd0e2cc commit 7c25c21

File tree

2 files changed

+96
-14
lines changed

2 files changed

+96
-14
lines changed

path.go

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ func (p *Path) Fs() afero.Fs {
7171
}
7272

7373
func (p *Path) doesNotImplementErr(interfaceName string) error {
74-
return errors.Wrapf(ErrDoesNotImplement, "Path's afero filesystem %s does not implement %s", getFsName(p.fs), interfaceName)
74+
return doesNotImplementErr(interfaceName, p.Fs())
75+
}
76+
77+
func doesNotImplementErr(interfaceName string, fs afero.Fs) error {
78+
return errors.Wrapf(ErrDoesNotImplement, "Path's afero filesystem %s does not implement %s", getFsName(fs), interfaceName)
7579
}
7680

7781
// *******************************
@@ -184,6 +188,12 @@ func (p *Path) IsDir() (bool, error) {
184188
return afero.IsDir(p.Fs(), p.Path())
185189
}
186190

191+
// IsDir returns whether or not the os.FileInfo object represents a
192+
// directory.
193+
func IsDir(fileInfo os.FileInfo) bool {
194+
return fileInfo.IsDir()
195+
}
196+
187197
// IsEmpty checks if a given file or directory is empty.
188198
func (p *Path) IsEmpty() (bool, error) {
189199
return afero.IsEmpty(p.Fs(), p.Path())
@@ -396,6 +406,20 @@ func (p *Path) RelativeTo(other *Path) (*Path, error) {
396406
return NewPathAfero(strings.Join(relativePath, "/"), p.Fs()), nil
397407
}
398408

409+
// Lstat lstat's the path if the underlying afero filesystem supports it. If
410+
// the filesystem does not support afero.Lstater, an error will be returned.
411+
// A nil os.FileInfo is returned on errors. Also returned is a boolean describing
412+
// whether or not Lstat was called (in cases where the filesystem is an OS filesystem)
413+
// or not called (in cases where only Stat is supported). See
414+
// https://godoc.org/github.com/spf13/afero#Lstater for more info.
415+
func (p *Path) Lstat() (os.FileInfo, bool, error) {
416+
lStater, ok := p.Fs().(afero.Lstater)
417+
if !ok {
418+
return nil, false, p.doesNotImplementErr("afero.Lstater")
419+
}
420+
return lStater.LstatIfPossible(p.Path())
421+
}
422+
399423
// *********************************
400424
// * filesystem-specific functions *
401425
// *********************************
@@ -422,32 +446,36 @@ func (p *Path) String() string {
422446

423447
// IsFile returns true if the given path is a file.
424448
func (p *Path) IsFile() (bool, error) {
425-
fileInfo, err := p.Fs().Stat(p.Path())
449+
fileInfo, err := p.Stat()
426450
if err != nil {
427451
return false, err
428452
}
453+
return IsFile(fileInfo)
454+
}
455+
456+
// IsFile returns whether or not the file described by the given
457+
// os.FileInfo is a regular file.
458+
func IsFile(fileInfo os.FileInfo) (bool, error) {
429459
return fileInfo.Mode().IsRegular(), nil
430460
}
431461

432462
// IsSymlink returns true if the given path is a symlink.
433463
// Fails if the filesystem doesn't implement afero.Lstater.
434464
func (p *Path) IsSymlink() (bool, error) {
435-
lStater, ok := p.Fs().(afero.Lstater)
436-
if !ok {
437-
return false, p.doesNotImplementErr("afero.Lstater")
438-
}
439-
fileInfo, lstatCalled, err := lStater.LstatIfPossible(p.Path())
440-
if err != nil || !lstatCalled {
441-
// If lstat wasn't called then the filesystem doesn't implement it.
442-
// Thus, it isn't a symlink
465+
fileInfo, _, err := p.Lstat()
466+
if err != nil {
443467
return false, err
444468
}
469+
return IsSymlink(fileInfo)
470+
}
445471

446-
isSymlink := false
472+
// IsSymlink returns true if the file described by the given
473+
// os.FileInfo describes a symlink.
474+
func IsSymlink(fileInfo os.FileInfo) (bool, error) {
447475
if fileInfo.Mode()&os.ModeSymlink != 0 {
448-
isSymlink = true
476+
return true, nil
449477
}
450-
return isSymlink, nil
478+
return false, nil
451479
}
452480

453481
// Path returns the string representation of the path
@@ -516,5 +544,26 @@ func (p *Path) Mtime() (time.Time, error) {
516544
if err != nil {
517545
return time.Time{}, err
518546
}
519-
return stat.ModTime(), nil
547+
return Mtime(stat)
548+
}
549+
550+
// Mtime returns the mtime described in the given os.FileInfo object
551+
func Mtime(fileInfo os.FileInfo) (time.Time, error) {
552+
return fileInfo.ModTime(), nil
553+
}
554+
555+
// Size returns the size of the object. Fails if the object doesn't exist.
556+
func (p *Path) Size() (int64, error) {
557+
stat, err := p.Stat()
558+
if err != nil {
559+
return 0, err
560+
}
561+
return Size(stat), nil
562+
}
563+
564+
// Size returns the size described by the os.FileInfo. Before you say anything,
565+
// yes... you could just do fileInfo.Size(). This is purely a convenience function
566+
// to create API consistency.
567+
func Size(fileInfo os.FileInfo) int64 {
568+
return fileInfo.Size()
520569
}

path_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,39 @@ func (p *PathSuite) TestRenamePath() {
135135
assert.False(p.T(), oldFileExists)
136136
}
137137

138+
func (p *PathSuite) TestSizeZero() {
139+
file := p.tmpdir.Join("file.txt")
140+
require.NoError(p.T(), file.WriteFile([]byte{}, 0o644))
141+
size, err := file.Size()
142+
require.NoError(p.T(), err)
143+
p.Zero(size)
144+
}
145+
146+
func (p *PathSuite) TestSizeNonZero() {
147+
msg := "oh, it's you"
148+
file := p.tmpdir.Join("file.txt")
149+
require.NoError(p.T(), file.WriteFile([]byte(msg), 0o644))
150+
size, err := file.Size()
151+
require.NoError(p.T(), err)
152+
p.Equal(len(msg), int(size))
153+
}
154+
155+
func (p *PathSuite) TestIsDir() {
156+
dir := p.tmpdir.Join("dir")
157+
require.NoError(p.T(), dir.Mkdir(0o755))
158+
isDir, err := dir.IsDir()
159+
require.NoError(p.T(), err)
160+
p.True(isDir)
161+
}
162+
163+
func (p *PathSuite) TestIsntDir() {
164+
file := p.tmpdir.Join("file.txt")
165+
require.NoError(p.T(), file.WriteFile([]byte("hello world!"), 0o644))
166+
isDir, err := file.IsDir()
167+
require.NoError(p.T(), err)
168+
p.False(isDir)
169+
}
170+
138171
func (p *PathSuite) TestGetLatest() {
139172
now := time.Now()
140173
for i := 0; i < 5; i++ {

0 commit comments

Comments
 (0)