mirror of
https://github.com/golang/go
synced 2024-11-11 19:21:37 -07:00
io/fs: add FormatFileInfo and FormatDirEntry functions
For #54451 Change-Id: I3214066f77b1398ac1f2786ea035c83f32f0a826 Reviewed-on: https://go-review.googlesource.com/c/go/+/489555 Run-TryBot: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
630ef2edc2
commit
72ba91902a
2
api/next/54451.txt
Normal file
2
api/next/54451.txt
Normal file
@ -0,0 +1,2 @@
|
||||
pkg io/fs, func FormatDirEntry(DirEntry) string #54451
|
||||
pkg io/fs, func FormatFileInfo(FileInfo) string #54451
|
76
src/io/fs/format.go
Normal file
76
src/io/fs/format.go
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// FormatFileInfo returns a formatted version of info for human readability.
|
||||
// Implementations of FileInfo can call this from a String method.
|
||||
// The output for a file named "hello.go", 100 bytes, mode 0o644, created
|
||||
// January 1, 1970 at noon is
|
||||
//
|
||||
// -rw-r--r-- 100 1970-01-01 12:00:00 hello.go
|
||||
func FormatFileInfo(info FileInfo) string {
|
||||
name := info.Name()
|
||||
b := make([]byte, 0, 40+len(name))
|
||||
b = append(b, info.Mode().String()...)
|
||||
b = append(b, ' ')
|
||||
|
||||
size := info.Size()
|
||||
var usize uint64
|
||||
if size >= 0 {
|
||||
usize = uint64(size)
|
||||
} else {
|
||||
b = append(b, '-')
|
||||
usize = uint64(-size)
|
||||
}
|
||||
var buf [20]byte
|
||||
i := len(buf) - 1
|
||||
for usize >= 10 {
|
||||
q := usize / 10
|
||||
buf[i] = byte('0' + usize - q*10)
|
||||
i--
|
||||
usize = q
|
||||
}
|
||||
buf[i] = byte('0' + usize)
|
||||
b = append(b, buf[i:]...)
|
||||
b = append(b, ' ')
|
||||
|
||||
b = append(b, info.ModTime().Format(time.DateTime)...)
|
||||
b = append(b, ' ')
|
||||
|
||||
b = append(b, name...)
|
||||
if info.IsDir() {
|
||||
b = append(b, '/')
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// FormatDirEntry returns a formatted version of dir for human readability.
|
||||
// Implementations of DirEntry can call this from a String method.
|
||||
// The outputs for a directory named subdir and a file named hello.go are:
|
||||
//
|
||||
// d subdir/
|
||||
// - hello.go
|
||||
func FormatDirEntry(dir DirEntry) string {
|
||||
name := dir.Name()
|
||||
b := make([]byte, 0, 5+len(name))
|
||||
|
||||
// The Type method does not return any permission bits,
|
||||
// so strip them from the string.
|
||||
mode := dir.Type().String()
|
||||
mode = mode[:len(mode)-9]
|
||||
|
||||
b = append(b, mode...)
|
||||
b = append(b, ' ')
|
||||
b = append(b, name...)
|
||||
if dir.IsDir() {
|
||||
b = append(b, '/')
|
||||
}
|
||||
return string(b)
|
||||
}
|
123
src/io/fs/format_test.go
Normal file
123
src/io/fs/format_test.go
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fs_test
|
||||
|
||||
import (
|
||||
. "io/fs"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// formatTest implements FileInfo to test FormatFileInfo,
|
||||
// and implements DirEntry to test FormatDirEntry.
|
||||
type formatTest struct {
|
||||
name string
|
||||
size int64
|
||||
mode FileMode
|
||||
modTime time.Time
|
||||
isDir bool
|
||||
}
|
||||
|
||||
func (fs *formatTest) Name() string {
|
||||
return fs.name
|
||||
}
|
||||
|
||||
func (fs *formatTest) Size() int64 {
|
||||
return fs.size
|
||||
}
|
||||
|
||||
func (fs *formatTest) Mode() FileMode {
|
||||
return fs.mode
|
||||
}
|
||||
|
||||
func (fs *formatTest) ModTime() time.Time {
|
||||
return fs.modTime
|
||||
}
|
||||
|
||||
func (fs *formatTest) IsDir() bool {
|
||||
return fs.isDir
|
||||
}
|
||||
|
||||
func (fs *formatTest) Sys() any {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *formatTest) Type() FileMode {
|
||||
return fs.mode.Type()
|
||||
}
|
||||
|
||||
func (fs *formatTest) Info() (FileInfo, error) {
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
var formatTests = []struct {
|
||||
input formatTest
|
||||
wantFileInfo string
|
||||
wantDirEntry string
|
||||
}{
|
||||
{
|
||||
formatTest{
|
||||
name: "hello.go",
|
||||
size: 100,
|
||||
mode: 0o644,
|
||||
modTime: time.Date(1970, time.January, 1, 12, 0, 0, 0, time.UTC),
|
||||
isDir: false,
|
||||
},
|
||||
"-rw-r--r-- 100 1970-01-01 12:00:00 hello.go",
|
||||
"- hello.go",
|
||||
},
|
||||
{
|
||||
formatTest{
|
||||
name: "home/gopher",
|
||||
size: 0,
|
||||
mode: ModeDir | 0o755,
|
||||
modTime: time.Date(1970, time.January, 1, 12, 0, 0, 0, time.UTC),
|
||||
isDir: true,
|
||||
},
|
||||
"drwxr-xr-x 0 1970-01-01 12:00:00 home/gopher/",
|
||||
"d home/gopher/",
|
||||
},
|
||||
{
|
||||
formatTest{
|
||||
name: "big",
|
||||
size: 0x7fffffffffffffff,
|
||||
mode: ModeIrregular | 0o644,
|
||||
modTime: time.Date(1970, time.January, 1, 12, 0, 0, 0, time.UTC),
|
||||
isDir: false,
|
||||
},
|
||||
"?rw-r--r-- 9223372036854775807 1970-01-01 12:00:00 big",
|
||||
"? big",
|
||||
},
|
||||
{
|
||||
formatTest{
|
||||
name: "small",
|
||||
size: -0x8000000000000000,
|
||||
mode: ModeSocket | ModeSetuid | 0o644,
|
||||
modTime: time.Date(1970, time.January, 1, 12, 0, 0, 0, time.UTC),
|
||||
isDir: false,
|
||||
},
|
||||
"Surw-r--r-- -9223372036854775808 1970-01-01 12:00:00 small",
|
||||
"S small",
|
||||
},
|
||||
}
|
||||
|
||||
func TestFormatFileInfo(t *testing.T) {
|
||||
for i, test := range formatTests {
|
||||
got := FormatFileInfo(&test.input)
|
||||
if got != test.wantFileInfo {
|
||||
t.Errorf("%d: FormatFileInfo(%#v) = %q, want %q", i, test.input, got, test.wantFileInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatDirEntry(t *testing.T) {
|
||||
for i, test := range formatTests {
|
||||
got := FormatDirEntry(&test.input)
|
||||
if got != test.wantDirEntry {
|
||||
t.Errorf("%d: FormatDirEntry(%#v) = %q, want %q", i, test.input, got, test.wantDirEntry)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user