go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/genctx.go (about) 1 // Copyright 2018 The LUCI 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 lucicfg 16 17 import ( 18 "fmt" 19 20 "go.starlark.net/starlark" 21 "go.starlark.net/starlarkstruct" 22 ) 23 24 // genCtx is a starlark struct that represents the state passed to generator 25 // callbacks (as first and only argument). 26 type genCtx struct { 27 starlarkstruct.Struct 28 29 output *outputBuilder 30 roots map[string]string // name of the set => its root directory 31 } 32 33 func newGenCtx() *genCtx { 34 ctx := &genCtx{ 35 output: newOutputBuilder(), 36 roots: map[string]string{}, 37 } 38 ctx.Struct = *starlarkstruct.FromStringDict(starlark.String("gen_ctx"), starlark.StringDict{ 39 "output": ctx.output, 40 "declare_config_set": starlark.NewBuiltin("declare_config_set", ctx.declareConfigSetImpl), 41 }) 42 return ctx 43 } 44 45 func (c *genCtx) declareConfigSetImpl(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 46 var name starlark.String 47 var root starlark.String 48 err := starlark.UnpackArgs("declare_config_set", args, kwargs, 49 "name", &name, 50 "root", &root) 51 if err != nil { 52 return nil, err 53 } 54 nameS := name.GoString() 55 56 // Paths must be within the config output directory, "../" is not allowed. 57 rootS, err := cleanRelativePath("", root.GoString(), false) 58 if err != nil { 59 return nil, fmt.Errorf("declare_config_set: root - %s", err) 60 } 61 62 // It is OK to redeclare exact same root. It is not OK to change it. 63 if existing, ok := c.roots[nameS]; ok && existing != rootS { 64 return nil, fmt.Errorf("declare_config_set: set %q has already been declared", nameS) 65 } 66 c.roots[nameS] = rootS 67 68 return starlark.None, nil 69 } 70 71 func (c *genCtx) assembleOutput(includePBHeader bool) (Output, error) { 72 files, err := c.output.finalize(includePBHeader) 73 return Output{ 74 Data: files, 75 Roots: c.roots, 76 }, err 77 } 78 79 func init() { 80 // new_gen_ctx() makes a new empty generator context object. 81 declNative("new_gen_ctx", func(call nativeCall) (starlark.Value, error) { 82 if err := call.unpack(0); err != nil { 83 return nil, err 84 } 85 return newGenCtx(), nil 86 }) 87 }