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
|
"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_look_path": FuncASRSE(exec.LookPath), // exec_look_path(file) => string/error
|
||||||
"exec": &objects.UserFunction{Value: osExec}, // exec(name, args...) => command
|
"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) {
|
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
|
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.
|
- `remove_all(name string) => error `: removes path and any children it contains.
|
||||||
- `rename(oldpath string, newpath string) => error `: renames (moves) oldpath to newpath.
|
- `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.
|
- `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.
|
- `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.
|
- `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.
|
- `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(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.
|
- `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.
|
- `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.
|
- `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.
|
- `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()
|
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
|
## Command
|
||||||
|
|
||||||
- `combined_output() => bytes/error`: runs the command and returns its combined standard output and standard error.
|
- `combined_output() => bytes/error`: runs the command and returns its combined standard output and standard error.
|
||||||
|
|
Loading…
Reference in a new issue