-
-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Time fields are omitted for now; they will be added when there's a proper Elvish binding for time.Time. This addresses #1659.
- Loading branch information
Showing
14 changed files
with
495 additions
and
32 deletions.
There are no files selected for viewing
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package os | ||
|
||
import ( | ||
"fmt" | ||
"io/fs" | ||
|
||
"src.elv.sh/pkg/eval/vals" | ||
) | ||
|
||
var typeNames = map[fs.FileMode]string{ | ||
0: "regular", | ||
fs.ModeDir: "dir", | ||
fs.ModeSymlink: "symlink", | ||
fs.ModeNamedPipe: "named-pipe", | ||
fs.ModeSocket: "socket", | ||
fs.ModeDevice: "device", | ||
fs.ModeDevice | fs.ModeCharDevice: "char-device", | ||
fs.ModeIrregular: "irregular", | ||
} | ||
|
||
var specialModeNames = [...]struct { | ||
bit fs.FileMode | ||
name string | ||
}{ | ||
// fs.ModeAppend, fs.ModeExclusive and fs.ModeTemporary are only used on | ||
// Plan 9, which Elvish doesn't support (yet). | ||
{fs.ModeSetuid, "setuid"}, | ||
{fs.ModeSetgid, "setgid"}, | ||
{fs.ModeSticky, "sticky"}, | ||
} | ||
|
||
// Implementation of the stat function itself is in os.go. | ||
|
||
func statMap(fi fs.FileInfo) vals.Map { | ||
mode := fi.Mode() | ||
typeName, ok := typeNames[mode.Type()] | ||
if !ok { | ||
// This shouldn't happen, but if there is a bug this gives us a bit of | ||
// information. | ||
typeName = fmt.Sprintf("unknown %d", mode.Type()) | ||
} | ||
// TODO: Make this a set when Elvish has a set type. | ||
specialModes := vals.EmptyList | ||
for _, special := range specialModeNames { | ||
if mode&special.bit != 0 { | ||
specialModes = specialModes.Conj(special.name) | ||
} | ||
} | ||
return vals.MakeMap( | ||
"name", fi.Name(), | ||
"size", vals.Int64ToNum(fi.Size()), | ||
"type", typeName, | ||
"perm", int(fi.Mode()&fs.ModePerm), | ||
"special-modes", specialModes, | ||
"sys", statSysMap(fi.Sys())) | ||
// TODO: ModTime | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
//go:build darwin || freebsd || netbsd || openbsd | ||
|
||
package os | ||
|
||
import "syscall" | ||
|
||
func init() { | ||
extraStatFields["gen"] = func(st *syscall.Stat_t) uint64 { return uint64(st.Gen) } | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package os_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"src.elv.sh/pkg/eval/vals" | ||
"src.elv.sh/pkg/must" | ||
) | ||
|
||
func TestStat(t *testing.T) { | ||
InTempDir(t) | ||
ApplyDir(Dir{ | ||
"dir": Dir{}, | ||
"file": "foobar", | ||
}) | ||
|
||
TestWithEvalerSetup(t, useOS, | ||
That(`os:stat file`).Puts(MapContainingPairs( | ||
"name", "file", | ||
"size", 6, | ||
"type", "regular", | ||
)), | ||
That(`os:stat dir`).Puts(MapContainingPairs( | ||
"name", "dir", | ||
// size field of directories is platform-dependent | ||
"type", "dir", | ||
)), | ||
That(`os:stat non-existent`).Throws(ErrorWithType(&os.PathError{})), | ||
) | ||
} | ||
|
||
func TestStat_Symlink(t *testing.T) { | ||
InTempDir(t) | ||
ApplyDir(Dir{"regular": ""}) | ||
err := os.Symlink("regular", "symlink") | ||
if err != nil { | ||
// On Windows we may or may not be able to create a symlink. | ||
t.Skipf("symlink: %v", err) | ||
} | ||
|
||
TestWithEvalerSetup(t, useOS, | ||
That(`os:stat symlink`). | ||
Puts(MapContainingPairs("type", "symlink")), | ||
That(`os:stat &follow-symlink=$true symlink`). | ||
Puts(MapContainingPairs("type", "regular")), | ||
) | ||
} | ||
|
||
var permAndSpecialModesTests = []struct { | ||
name string | ||
mode os.FileMode | ||
statMap vals.Map | ||
}{ | ||
{"444", 0o444, vals.MakeMap("perm", 0o444)}, | ||
{"666", 0o666, vals.MakeMap("perm", 0o666)}, | ||
{"setuid", os.ModeSetuid, vals.MakeMap("special-modes", vals.MakeList("setuid"))}, | ||
{"setgid", os.ModeSetgid, vals.MakeMap("special-modes", vals.MakeList("setgid"))}, | ||
{"sticky", os.ModeSticky, vals.MakeMap("special-modes", vals.MakeList("sticky"))}, | ||
} | ||
|
||
func TestStat_PermAndSpecialModes(t *testing.T) { | ||
Umask(t, 0) | ||
for _, test := range permAndSpecialModesTests { | ||
t.Run(test.name, func(t *testing.T) { | ||
InTempDir(t) | ||
must.OK(os.WriteFile("file", nil, 0o666)) | ||
ChmodOrSkip(t, "file", test.mode) | ||
|
||
TestWithEvalerSetup(t, useOS, | ||
That(`os:stat file`).Puts(MapContaining(test.statMap)), | ||
) | ||
}) | ||
} | ||
} |
Oops, something went wrong.