this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

pkg/tool: add constraints for tasks

Updates #39

Change-Id: Ied624912324b773b56ff4f2a1bf85a88c22ecc45
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/1924
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>

authored by

Marcel van Lohuizen and committed by
Marcel van Lohuizen
f8132853 10fd4964

+561 -28
+21 -1
cmd/cue/cmd/custom.go
··· 29 29 "sync" 30 30 31 31 "cuelang.org/go/cue" 32 + "cuelang.org/go/internal" 32 33 itask "cuelang.org/go/internal/task" 33 34 _ "cuelang.org/go/pkg/tool/cli" // Register tasks 34 35 _ "cuelang.org/go/pkg/tool/exec" ··· 251 252 dep map[*task]bool 252 253 } 253 254 255 + var oldKinds = map[string]string{ 256 + "exec": "tool/exec.Run", 257 + "http": "tool/http.Do", 258 + "print": "tool/cli.Print", 259 + "testserver": "cmd/cue/cmd.Test", 260 + } 261 + 254 262 func newTask(index int, name string, v cue.Value) (*task, error) { 263 + // Lookup kind for backwards compatibility. 264 + // TODO: consider at some point whether kind can be removed. 255 265 kind, err := v.Lookup("kind").String() 256 266 if err != nil { 257 267 return nil, err 258 268 } 269 + if k, ok := oldKinds[kind]; ok { 270 + kind = k 271 + } 259 272 rf := itask.Lookup(kind) 260 273 if rf == nil { 261 274 return nil, fmt.Errorf("runner of kind %q not found", kind) 262 275 } 276 + 277 + // Verify entry against template. 278 + v = internal.UnifyBuiltin(v, kind).(cue.Value) 279 + if err := v.Err(); err != nil { 280 + return nil, err 281 + } 282 + 263 283 runner, err := rf(v) 264 284 if err != nil { 265 285 return nil, err ··· 278 298 } 279 299 280 300 func init() { 281 - itask.Register("testserver", newTestServerCmd) 301 + itask.Register("cmd/cue/cmd.Test", newTestServerCmd) 282 302 } 283 303 284 304 var testOnce sync.Once
+2 -1
cmd/cue/cmd/testdata/tasks/cmd_baddisplay.out
··· 1 - not of right kind (number vs string): 1 + unsupported op &(number, (string)*): 2 2 $CWD/testdata/tasks/task_tool.cue:29:9 3 + tool/cli:4:10 3 4
+22
cue/builtin.go
··· 23 23 "math/big" 24 24 "path" 25 25 "sort" 26 + "strings" 26 27 27 28 "cuelang.org/go/cue/errors" 28 29 "cuelang.org/go/cue/parser" 30 + "cuelang.org/go/internal" 29 31 ) 30 32 31 33 // A builtin is a builtin function or constant. ··· 248 250 return nil 249 251 } 250 252 return p 253 + } 254 + 255 + func init() { 256 + internal.UnifyBuiltin = func(val interface{}, kind string) interface{} { 257 + v := val.(Value) 258 + ctx := v.ctx() 259 + 260 + p := strings.Split(kind, ".") 261 + pkg, name := p[0], p[1] 262 + s := getBuiltinPkg(ctx, pkg) 263 + if s == nil { 264 + return v 265 + } 266 + a := s.lookup(ctx, ctx.label(name, false)) 267 + if a.v == nil { 268 + return v 269 + } 270 + 271 + return v.Unify(newValueRoot(ctx, a.v.evalPartial(ctx))) 272 + } 251 273 } 252 274 253 275 // do returns whether the call should be done.
+106 -15
cue/builtins.go
··· 466 466 }, 467 467 }}, 468 468 }, 469 - "list": &builtinPkg{ 470 - native: []*builtin{{}}, 471 - }, 472 469 "math": &builtinPkg{ 473 470 native: []*builtin{{ 474 471 Name: "MaxExp", ··· 1297 1294 }, 1298 1295 }}, 1299 1296 }, 1300 - "runtime": &builtinPkg{ 1301 - native: []*builtin{{ 1302 - Name: "Path", 1303 - Params: []kind{}, 1304 - Result: stringKind, 1305 - Func: func(c *callCtxt) { 1306 - c.ret = func() interface{} { 1307 - return "" 1308 - }() 1309 - }, 1310 - }}, 1311 - }, 1312 1297 "strconv": &builtinPkg{ 1313 1298 native: []*builtin{{ 1314 1299 Name: "Unquote", ··· 1880 1865 native: []*builtin{{}}, 1881 1866 cue: `{ 1882 1867 Time: null | =~"^\("\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\\d|3[0-1])")T\("([0-1]\\d|2[0-3]):[0-5]\\d:[0-5]\\d")\("(.\\d{1,10})?")\("(Z|(-|\\+)\\d\\d:\\d\\d)")$" 1868 + }`, 1869 + }, 1870 + "tool": &builtinPkg{ 1871 + native: []*builtin{{}}, 1872 + cue: `{ 1873 + Command: { 1874 + usage?: string 1875 + short?: string 1876 + long?: string 1877 + var <name>: { 1878 + value: _ 1879 + description: "" | string 1880 + } 1881 + tasks <name>: Task 1882 + } 1883 + Task _kind: =~"\\." 1884 + }`, 1885 + }, 1886 + "tool/cli": &builtinPkg{ 1887 + native: []*builtin{{}}, 1888 + cue: `{ 1889 + Print: { 1890 + _kind: "tool/cli.Print" 1891 + text: string 1892 + } 1893 + }`, 1894 + }, 1895 + "tool/exec": &builtinPkg{ 1896 + native: []*builtin{{}}, 1897 + cue: `{ 1898 + Run: { 1899 + _kind: "tool/exec.Run" 1900 + cmd: string | [string, ...string] 1901 + install?: string | [string, ...string] 1902 + env <Key>: string 1903 + stdout: *null | string | bytes 1904 + stderr: *null | string | bytes 1905 + stdin?: string | bytes 1906 + success: bool 1907 + } 1908 + Env: { 1909 + _kind: "tool/exec.Env" 1910 + env <Name>: string | number 1911 + } 1912 + }`, 1913 + }, 1914 + "tool/file": &builtinPkg{ 1915 + native: []*builtin{{}}, 1916 + cue: `{ 1917 + Read: { 1918 + _kind: "tool/file.Read" 1919 + filename: !="" 1920 + contents: *bytes | string 1921 + } 1922 + Create: { 1923 + _kind: "tool/file.Create" 1924 + filename: !="" 1925 + contents: bytes | string 1926 + permissions: int | *420 1927 + overwrite: *false | true 1928 + } 1929 + Append: { 1930 + _kind: "tool/file.Append" 1931 + filename: !="" 1932 + contents: bytes | string 1933 + permissions: int | *420 1934 + } 1935 + Glob: { 1936 + _kind: "tool/file.Glob" 1937 + glob: !="" 1938 + files: [...string] 1939 + } 1940 + }`, 1941 + }, 1942 + "tool/http": &builtinPkg{ 1943 + native: []*builtin{{}}, 1944 + cue: `{ 1945 + Get: Do & { 1946 + method: "GET" 1947 + } 1948 + Do: { 1949 + _kind: "tool/http.Do" 1950 + method: string 1951 + response: { 1952 + body: *bytes | string 1953 + header <Name>: string | [...string] 1954 + trailer <Name>: string | [...string] 1955 + status: string 1956 + statusCode: int 1957 + } 1958 + url: string 1959 + request: { 1960 + body: *bytes | string 1961 + header <Name>: string | [...string] 1962 + trailer <Name>: string | [...string] 1963 + } 1964 + } 1965 + Post: Do & { 1966 + method: "POST" 1967 + } 1968 + Put: Do & { 1969 + method: "PUT" 1970 + } 1971 + Delete: Do & { 1972 + method: "DELETE" 1973 + } 1883 1974 }`, 1884 1975 }, 1885 1976 }
+3 -3
cue/gen.go
··· 203 203 return 204 204 } 205 205 206 + n := instances[0].Value().Syntax(cue.Hidden(true), cue.Concrete(false)) 206 207 var buf bytes.Buffer 207 - if err := cueformat.Node(&buf, instances[0].Value().Syntax()); err != nil { 208 + if err := cueformat.Node(&buf, n); err != nil { 208 209 log.Fatal(err) 209 210 } 210 211 body := buf.String() ··· 250 251 fmt.Fprint(g.decls, "\n\n") 251 252 continue 252 253 case token.TYPE: 254 + // TODO: support type declarations. 253 255 for _, spec := range x.Specs { 254 256 if ast.IsExported(spec.(*ast.TypeSpec).Name.Name) { 255 257 log.Fatal("type declarations not supported") 256 258 } 257 259 } 258 - printer.Fprint(g.decls, g.fset, x) 259 - fmt.Fprint(g.decls, "\n\n") 260 260 continue 261 261 default: 262 262 log.Fatalf("unexpected spec of type %s", x.Tok)
+8 -8
cue/resolve_test.go
··· 1748 1748 result: [ v for _, v in service ] 1749 1749 1750 1750 service <Name>: { 1751 - type: "service" 1752 1751 name: *Name | string 1752 + type: "service" 1753 1753 port: *7080 | int 1754 1754 } 1755 1755 service foo: {} ··· 1757 1757 service baz: { name: "foobar" } 1758 1758 `, 1759 1759 out: `<0>{result: [` + 1760 - `<1>{type: "service", name: "foo", port: 7080},` + 1761 - `<2>{type: "service", name: "bar", port: 8000},` + 1762 - `<3>{type: "service", name: "foobar", port: 7080}], ` + 1760 + `<1>{name: "foo", type: "service", port: 7080},` + 1761 + `<2>{name: "bar", type: "service", port: 8000},` + 1762 + `<3>{name: "foobar", type: "service", port: 7080}], ` + 1763 1763 1764 1764 `service: <4>{` + 1765 - `<>: <5>(Name: string)-><6>{type: "service", name: (*<5>.Name | string), port: (*7080 | int)}, ` + 1766 - `foo: <7>{type: "service", name: "foo", port: 7080}, ` + 1767 - `bar: <8>{type: "service", name: "bar", port: 8000}, ` + 1768 - `baz: <9>{type: "service", name: "foobar", port: 7080}}}`, 1765 + `<>: <5>(Name: string)-><6>{name: (*<5>.Name | string), type: "service", port: (*7080 | int)}, ` + 1766 + `foo: <7>{name: "foo", type: "service", port: 7080}, ` + 1767 + `bar: <8>{name: "bar", type: "service", port: 8000}, ` + 1768 + `baz: <9>{name: "foobar", type: "service", port: 7080}}}`, 1769 1769 }, { 1770 1770 desc: "resolutions in struct comprehension keys", 1771 1771 in: `
+3
internal/internal.go
··· 43 43 // DropOptional is a blanket override of handling optional values during 44 44 // compilation. TODO: should we make this a build option? 45 45 var DropOptional bool 46 + 47 + // UnifyBuiltin returns the given Value unified with the given builtin template. 48 + var UnifyBuiltin func(v interface{}, kind string) interface{}
+42
pkg/tool/cli/cli.cue
··· 1 + // Copyright 2018 The CUE Authors 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package cli 16 + 17 + // Print sends text to the stdout of the current process. 18 + Print: { 19 + kind: "tool/cli.Print" 20 + 21 + // text is the text to be printed. 22 + text: string 23 + } 24 + 25 + // TODO: 26 + // Ask prompts the current console with a message and waits for input. 27 + // 28 + // Example: 29 + // task ask: cli.Ask({ 30 + // prompt: "Are you okay?" 31 + // repsonse: bool 32 + // }) 33 + // Ask: { 34 + // kind: "tool/cli.Ask" 35 + 36 + // // prompt sends this message to the output. 37 + // prompt: string 38 + 39 + // // response holds the user's response. If it is a boolean expression it 40 + // // will interpret the answer using textual yes/ no. 41 + // response: string | bool 42 + // }
+53
pkg/tool/exec/exec.cue
··· 1 + // Copyright 2018 The CUE Authors 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package exec 16 + 17 + // Run executes the given shell command. 18 + Run: { 19 + kind: "tool/exec.Run" 20 + 21 + // cmd is the command to run. 22 + cmd: string | [string, ...string] 23 + 24 + // install is an optional command to install the binaries needed 25 + // to run the command. 26 + install?: string | [string, ...string] 27 + 28 + // env defines the environment variables to use for this system. 29 + env <Key>: string 30 + 31 + // stdout captures the output from stdout if it is of type bytes or string. 32 + // The default value of null indicates it is redirected to the stdout of the 33 + // current process. 34 + stdout: *null | string | bytes 35 + 36 + // stderr is like stdout, but for errors. 37 + stderr: *null | string | bytes 38 + 39 + // stdin specifies the input for the process. 40 + stdin?: string | bytes 41 + 42 + // success is set to true when the process terminates with with a zero exit 43 + // code or false otherwise. The user can explicitly specify the value 44 + // force a fatal error if the desired success code is not reached. 45 + success: bool 46 + } 47 + 48 + // Env collects the environment variables of the current process. 49 + Env: { 50 + kind: "tool/exec.Env" 51 + 52 + env <Name>: string | number 53 + }
+77
pkg/tool/file/file.cue
··· 1 + // Copyright 2018 The CUE Authors 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package os 16 + 17 + import "tool" 18 + 19 + // Read reads the contents of a file. 20 + Read: tool.Task & { 21 + _kind: "tool/file.Read" 22 + 23 + // filename names the file to read. 24 + filename: string 25 + 26 + // contents is the read contents. If the contents are constraint to bytes 27 + // (the default), the file is read as is. If it is constraint to a string, 28 + // the contents are checked to be valid UTF-8. 29 + contents: *bytes | string 30 + 31 + // if body is given, the file contents are parsed as JSON and unified with 32 + // the specified CUE value. 33 + body?: _ 34 + } 35 + 36 + // Create writes contents to the given file. 37 + Create: tool.Task & { 38 + _kind: "tool/file.Create" 39 + 40 + // filename names the file to write. 41 + filename: string 42 + 43 + // permissions defines the permissions to use if the file does not yet exist. 44 + permissions: int 45 + 46 + // overwrite defines whether an existing file may be overwritten. 47 + overwrite: *false | true 48 + 49 + // contents specifies the bytes to be written. 50 + contents: bytes | string 51 + } 52 + 53 + // Append writes contents to the given file. 54 + Append: tool.Task & { 55 + // filename names the file to append. 56 + filename: string 57 + 58 + // permissions defines the permissions to use if the file does not yet exist. 59 + permissions: int 60 + 61 + // contents specifies the bytes to be written. 62 + contents: bytes | string 63 + } 64 + 65 + Dir: tool.Task & { 66 + _kind: "tool/file.Dir" 67 + 68 + path: string 69 + dir: [...string] 70 + } 71 + 72 + Glob: tool.Task & { 73 + _kind: "tool/file.Glob" 74 + 75 + glob: string 76 + files <Filename>: string 77 + }
+54
pkg/tool/http/http.cue
··· 1 + // Copyright 2018 The CUE Authors 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + package http 16 + 17 + Get: Do & {method: "GET"} 18 + Post: Do & {method: "POST"} 19 + Put: Do & {method: "PUT"} 20 + Delete: Do & {method: "DELETE"} 21 + 22 + Do: { 23 + kind: "tool/http.Do" 24 + 25 + method: string 26 + url: string // TODO: make url.URL type 27 + 28 + request: { 29 + body: *bytes | string 30 + header <Name>: string | [...string] 31 + trailer <Name>: string | [...string] 32 + } 33 + response: { 34 + status: string 35 + statusCode: int 36 + 37 + body: *bytes | string 38 + header <Name>: string | [...string] 39 + trailer <Name>: string | [...string] 40 + } 41 + } 42 + 43 + /* TODO: support serving once we have the cue serve command. 44 + Serve: { 45 + port: int 46 + 47 + cert: string 48 + key: string 49 + 50 + handle <Pattern>: Message & { 51 + pattern: Pattern 52 + } 53 + } 54 + */
+170
pkg/tool/tool.cue
··· 1 + // Copyright 2018 The CUE Authors 2 + // 3 + // Licensed under the Apache License, Version 2.0 (the "License"); 4 + // you may not use this file except in compliance with the License. 5 + // You may obtain a copy of the License at 6 + // 7 + // http://www.apache.org/licenses/LICENSE-2.0 8 + // 9 + // Unless required by applicable law or agreed to in writing, software 10 + // distributed under the License is distributed on an "AS IS" BASIS, 11 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 + // See the License for the specific language governing permissions and 13 + // limitations under the License. 14 + 15 + // Package tool defines statefull operation types for cue commands. 16 + // 17 + // This package is only visible in cue files with a _tool.cue or _tool_test.cue 18 + // ending. 19 + // 20 + // CUE configuration files are not influenced by and do not influence anything 21 + // outside the configuration itself: they are hermetic. Tools solve 22 + // two problems: allow outside values such as environment variables, 23 + // file or web contents, random generators etc. to influence configuration, 24 + // and allow configuration to be actionable from within the tooling itself. 25 + // Separating these concerns makes it clear to user when outside influences are 26 + // in play and the tool definition can be strict about what is allowed. 27 + // 28 + // Tools are defined in files ending with _tool.cue. These files have a 29 + // top-level map, "command", which defines all the tools made available through 30 + // the cue command. 31 + // 32 + // 33 + package tool 34 + 35 + // A Command specifies a user-defined command. 36 + Command: { 37 + // 38 + // Example: 39 + // mycmd [-n] names 40 + usage?: string 41 + 42 + // short is short description of what the command does. 43 + short?: string 44 + 45 + // long is a longer description that spans multiple lines and 46 + // likely contain examples of usage of the command. 47 + long?: string 48 + 49 + // A var defines a value that can be set by the command line or an 50 + // environment variable. 51 + // 52 + // Example: 53 + // var fast: { 54 + // description: "run faster than anyone" 55 + // value: true | bool 56 + // } 57 + // 58 + var <name>: { 59 + value: _ 60 + description: "" | string 61 + } 62 + 63 + // tasks specifies the list of things to do to run command. Tasks are 64 + // typically underspecified and completed by the particular internal 65 + // handler that is running them. Task de 66 + tasks <name>: Task 67 + 68 + // TODO: 69 + // timeout?: number // in seconds 70 + } 71 + 72 + // A task defines a step in the execution of a command, server, or fix 73 + // operation. 74 + Task: { 75 + kind: =~#"\."# 76 + } 77 + 78 + // import "cue/tool" 79 + // 80 + // command <Name>: { // from "cue/tool".Command 81 + // // usage gives a short usage pattern of the command. 82 + // // Example: 83 + // // fmt [-n] [-x] [packages] 84 + // usage: Name | string 85 + // 86 + // // short gives a brief on-line description of the command. 87 + // // Example: 88 + // // reformat package sources 89 + // short: "" | string 90 + // 91 + // // long gives a detailed description of the command, including a 92 + // // description of flags usage and examples. 93 + // long: "" | string 94 + // 95 + // // A task defines a single action to be run as part of this command. 96 + // // Each task can have inputs and outputs, depending on the type 97 + // // task. The outputs are initially unspecified, but are filled out 98 + // // by the tooling 99 + // // 100 + // task <Name>: { // from "cue/tool".Task 101 + // // supported fields depend on type 102 + // } 103 + // 104 + // VarValue = string | bool | int | float | [...string|int|float] 105 + // 106 + // // var declares values that can be set by command line flags or 107 + // // environment variables. 108 + // // 109 + // // Example: 110 + // // // environment to run in 111 + // // var env: "test" | "prod" 112 + // // The tool would print documentation of this flag as: 113 + // // Flags: 114 + // // --env string environment to run in: test(default) or prod 115 + // var <Name>: VarValue 116 + // 117 + // // flag defines a command line flag. 118 + // // 119 + // // Example: 120 + // // var env: "test" | "prod" 121 + // // 122 + // // // augment the flag information for var 123 + // // flag env: { 124 + // // shortFlag: "e" 125 + // // description: "environment to run in" 126 + // // } 127 + // // 128 + // // The tool would print documentation of this flag as: 129 + // // Flags: 130 + // // -e, --env string environment to run in: test(default), staging, or prod 131 + // // 132 + // flag <Name>: { // from "cue/tool".Flag 133 + // // value defines the possible values for this flag. 134 + // // The default is string. Users can define default values by 135 + // // using disjunctions. 136 + // value: env[Name].value | VarValue 137 + // 138 + // // name, if set, allows var to be set with the command-line flag 139 + // // of the given name. null disables the command line flag. 140 + // name: Name | null | string 141 + // 142 + // // short defines an abbreviated version of the flag. 143 + // // Disabled by default. 144 + // short: null | string 145 + // } 146 + // 147 + // // populate flag with the default values for 148 + // flag: { "\(k)": { value: v } | null for k, v in var } 149 + // 150 + // // env defines environment variables. It is populated with values 151 + // // for var. 152 + // // 153 + // // To specify a var without an equivalent environment variable, 154 + // // either specify it as a flag directly or disable the equally 155 + // // named env entry explicitly: 156 + // // 157 + // // var foo: string 158 + // // env foo: null // don't use environment variables for foo 159 + // // 160 + // env <Name>: {å 161 + // // name defines the environment variable that sets this flag. 162 + // name: "CUE_VAR_" + strings.Upper(Name) | string | null 163 + // 164 + // // The value retrieved from the environment variable or null 165 + // // if not set. 166 + // value: null | string | bytes 167 + // } 168 + // env: { "\(k)": { value: v } | null for k, v in var } 169 + // } 170 + //