commit
a9224a3593
4 changed files with 126 additions and 0 deletions
|
@ -77,6 +77,40 @@ var osModule = map[string]objects.Object{
|
|||
"start_process": &objects.UserFunction{Value: osStartProcess}, // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error
|
||||
"exec_look_path": FuncASRSE(exec.LookPath), // exec_look_path(file) => string/error
|
||||
"exec": &objects.UserFunction{Value: osExec}, // exec(name, args...) => command
|
||||
"stat": &objects.UserFunction{Value: osStat}, // stat(name) => imap(fileinfo)/error
|
||||
}
|
||||
|
||||
func osStat(args ...objects.Object) (ret objects.Object, err error) {
|
||||
if len(args) != 1 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
fname, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, objects.ErrInvalidTypeConversion
|
||||
}
|
||||
|
||||
stat, err := os.Stat(fname)
|
||||
if err != nil {
|
||||
return wrapError(err), nil
|
||||
}
|
||||
|
||||
fstat := &objects.ImmutableMap{
|
||||
Value: map[string]objects.Object{
|
||||
"name": &objects.String{Value: stat.Name()},
|
||||
"mtime": &objects.Time{Value: stat.ModTime()},
|
||||
"size": &objects.Int{Value: stat.Size()},
|
||||
"mode": &objects.Int{Value: int64(stat.Mode())},
|
||||
},
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
fstat.Value["directory"] = objects.TrueValue
|
||||
} else {
|
||||
fstat.Value["directory"] = objects.FalseValue
|
||||
}
|
||||
|
||||
return fstat, nil
|
||||
}
|
||||
|
||||
func osCreate(args ...objects.Object) (objects.Object, error) {
|
||||
|
|
|
@ -66,6 +66,16 @@ func makeOSFile(file *os.File) *objects.ImmutableMap {
|
|||
return &objects.Int{Value: res}, nil
|
||||
},
|
||||
},
|
||||
// stat() => imap(fileinfo)/error
|
||||
"stat": &objects.UserFunction{
|
||||
Value: func(args ...objects.Object) (ret objects.Object, err error) {
|
||||
if len(args) != 0 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
return osStat(&objects.String{Value: file.Name()})
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
72
compiler/stdlib/os_test.go
Normal file
72
compiler/stdlib/os_test.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
package stdlib_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/d5/tengo/objects"
|
||||
)
|
||||
|
||||
func TestFileStatArgs(t *testing.T) {
|
||||
module(t, "os").call("stat").expectError()
|
||||
}
|
||||
|
||||
func TestFileStatFile(t *testing.T) {
|
||||
content := []byte("the quick brown fox jumps over the lazy dog")
|
||||
tf, err := ioutil.TempFile("", "test")
|
||||
if err != nil {
|
||||
t.Logf("could not open tempfile: %s", err)
|
||||
return
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
|
||||
_, err = tf.Write(content)
|
||||
if err != nil {
|
||||
t.Logf("could not write temp content: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
tf.Close()
|
||||
|
||||
stat, err := os.Stat(tf.Name())
|
||||
if err != nil {
|
||||
t.Logf("could not get tmp file stat: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
module(t, "os").call("stat", tf.Name()).expect(&objects.ImmutableMap{
|
||||
Value: map[string]objects.Object{
|
||||
"name": &objects.String{Value: stat.Name()},
|
||||
"mtime": &objects.Time{Value: stat.ModTime()},
|
||||
"size": &objects.Int{Value: stat.Size()},
|
||||
"mode": &objects.Int{Value: int64(stat.Mode())},
|
||||
"directory": objects.FalseValue,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestFileStatDir(t *testing.T) {
|
||||
td, err := ioutil.TempDir("", "test")
|
||||
if err != nil {
|
||||
t.Logf("could not open tempdir: %s", err)
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
stat, err := os.Stat(td)
|
||||
if err != nil {
|
||||
t.Logf("could not get tmp dir stat: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
module(t, "os").call("stat", td).expect(&objects.ImmutableMap{
|
||||
Value: map[string]objects.Object{
|
||||
"name": &objects.String{Value: stat.Name()},
|
||||
"mtime": &objects.Time{Value: stat.ModTime()},
|
||||
"size": &objects.Int{Value: stat.Size()},
|
||||
"mode": &objects.Int{Value: int64(stat.Mode())},
|
||||
"directory": objects.TrueValue,
|
||||
},
|
||||
})
|
||||
}
|
|
@ -68,6 +68,7 @@ os := import("os")
|
|||
- `remove_all(name string) => error `: removes path and any children it contains.
|
||||
- `rename(oldpath string, newpath string) => error `: renames (moves) oldpath to newpath.
|
||||
- `setenv(key string, value string) => error `: sets the value of the environment variable named by the key.
|
||||
- `stat(filename string) => FileInfo/error`: returns a file info structure describing the file
|
||||
- `symlink(oldname string newname string) => error `: creates newname as a symbolic link to oldname.
|
||||
- `temp_dir() => string `: returns the default directory to use for temporary files.
|
||||
- `truncate(name string, size int) => error `: changes the size of the named file.
|
||||
|
@ -98,6 +99,7 @@ file.close()
|
|||
- `write(bytes) => int/error`: writes len(b) bytes to the File.
|
||||
- `write_string(string) => int/error`: is like 'write', but writes the contents of string s rather than a slice of bytes.
|
||||
- `read(bytes) => int/error`: reads up to len(b) bytes from the File.
|
||||
- `stat() => FileInfo/error`: returns a file info structure describing the file
|
||||
- `chmod(mode int) => error`: changes the mode of the file to mode.
|
||||
- `seek(offset int, whence int) => int/error`: sets the offset for the next Read or Write on file to offset, interpreted according to whence: 0 means relative to the origin of the file, 1 means relative to the current offset, and 2 means relative to the end.
|
||||
|
||||
|
@ -131,6 +133,14 @@ cmd := exec.command("echo", ["foo", "bar"])
|
|||
output := cmd.output()
|
||||
```
|
||||
|
||||
## FileInfo
|
||||
|
||||
- `name`: name of the file the info describes
|
||||
- `mtime`: time the file was last modified
|
||||
- `size`: file size in bytes
|
||||
- `mode`: file permissions as in int, comparable to octal permissions
|
||||
- `directory`: boolean indicating if the file is a directory
|
||||
|
||||
## Command
|
||||
|
||||
- `combined_output() => bytes/error`: runs the command and returns its combined standard output and standard error.
|
||||
|
|
Loading…
Reference in a new issue