github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/internal/cmd/embedpkg/embedpkg.go (about) 1 // Copyright 2021 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 // embedpkg accepts a [packages] argument (see 'go help packages') and creates 16 // a map[string][]byte for each package argument, a map that represents the 17 // GoFiles for that package. The principal use case here is the embedding 18 // of the github.com/joomcode/cue/cmd/cue/cmd/interfaces used by cue get go. 19 package main 20 21 import ( 22 "bytes" 23 "flag" 24 "io/ioutil" 25 "log" 26 "path/filepath" 27 "text/template" 28 29 "golang.org/x/tools/go/packages" 30 ) 31 32 const genTmpl = `// Code generated by internal/cmd/embedpkg. DO NOT EDIT. 33 34 package cmd 35 36 // {{ .Basename }}Files is the result of embedding GoFiles from the 37 // {{ .PkgPath }} package. 38 var {{ .Basename }}Files = map[string][]byte { 39 {{- range $fn, $content := .GoFiles }} 40 "{{ $fn }}": {{ printf "%#v" $content }}, 41 {{- end }} 42 } 43 ` 44 45 func main() { 46 log.SetFlags(0) 47 flag.Parse() 48 49 cfg := &packages.Config{ 50 Mode: packages.NeedName | packages.NeedFiles | 51 packages.NeedCompiledGoFiles | packages.NeedModule, 52 } 53 pkgs, err := packages.Load(cfg, flag.Args()...) 54 if err != nil { 55 log.Fatal(err) 56 } 57 58 // parse template 59 tmpl, err := template.New("embedpkg").Parse(genTmpl) 60 if err != nil { 61 log.Fatal(err) 62 } 63 64 for _, p := range pkgs { 65 if packages.PrintErrors(pkgs) > 0 { 66 // The errors will already have been printed 67 log.Fatalln("error loading packages") 68 } 69 files := map[string][]byte{} 70 for _, fn := range p.GoFiles { 71 // Because of https://github.com/golang/go/issues/38445 we don't have p.Dir 72 content, err := ioutil.ReadFile(fn) 73 if err != nil { 74 log.Fatal(err) 75 } 76 relFile, err := filepath.Rel(p.Module.Dir, fn) 77 if err != nil { 78 log.Fatal(err) 79 } 80 files[relFile] = content 81 } 82 data := struct { 83 Basename string 84 PkgPath string 85 GoFiles map[string][]byte 86 }{ 87 Basename: p.Name, 88 PkgPath: p.PkgPath, 89 GoFiles: files, 90 } 91 var b bytes.Buffer 92 err = tmpl.Execute(&b, data) 93 if err != nil { 94 log.Fatal(err) 95 } 96 err = ioutil.WriteFile(filepath.Join(p.Name+"_gen.go"), b.Bytes(), 0666) 97 if err != nil { 98 log.Fatal(err) 99 } 100 } 101 }