github.com/octohelm/cuemod@v0.9.4/pkg/cuemod/modfile/load.go (about) 1 package modfile 2 3 import ( 4 "os" 5 "path/filepath" 6 "strconv" 7 "strings" 8 9 "cuelang.org/go/cue/ast" 10 "cuelang.org/go/cue/parser" 11 "cuelang.org/go/cue/token" 12 ) 13 14 func LoadModFile(dir string, m *ModFile) (bool, error) { 15 f := filepath.Join(dir, ModFilename) 16 17 if m.comments == nil { 18 m.comments = map[string][]*ast.CommentGroup{} 19 } 20 21 if m.Replace == nil { 22 m.Replace = map[VersionedPathIdentity]ReplaceTarget{} 23 } 24 25 if m.Require == nil { 26 m.Require = map[string]Requirement{} 27 } 28 29 data, err := os.ReadFile(f) 30 if err != nil && !os.IsNotExist(err) { 31 return false, err 32 } 33 34 if len(data) > 0 { 35 f, err := parser.ParseFile(ModFilename, data, parser.ParseComments) 36 if err != nil { 37 return false, err 38 } 39 40 for i := range f.Decls { 41 decl := f.Decls[i] 42 if field, ok := decl.(*ast.Field); ok { 43 directive := stringValue(field.Label) 44 45 if directive != "" { 46 switch directive { 47 case "module": 48 if module := stringValue(field.Value); module != "" { 49 m.Module = module 50 } 51 case "replace": 52 if s, ok := field.Value.(*ast.StructLit); ok { 53 for i := range s.Elts { 54 if subField, ok := s.Elts[i].(*ast.Field); ok { 55 from := stringValue(subField.Label) 56 to := stringValue(subField.Value) 57 58 if from != "" { 59 cg := ast.Comments(subField) 60 61 // from: xxx: xxx 62 if s.Lbrace == token.NoPos { 63 cg = ast.Comments(field) 64 } 65 66 m.comments[directive+"://"+from] = cg 67 68 r, err := ParsePathMayWithVersion(from) 69 if err != nil { 70 return false, err 71 } 72 73 replaceTarget := ReplaceTarget{} 74 75 if to != "" { 76 if err := replaceTarget.UnmarshalText([]byte(to)); err != nil { 77 return false, err 78 } 79 } 80 81 for i := range subField.Attrs { 82 k, v := subField.Attrs[i].Split() 83 84 switch k { 85 case "import": 86 value, _ := strconv.Unquote(v) 87 replaceTarget.Import = value 88 } 89 } 90 91 if replaceTarget.Path == "" { 92 replaceTarget.Path = r.Path 93 } 94 95 m.Replace[*r] = replaceTarget 96 } 97 } 98 } 99 } 100 case "require": 101 if s, ok := field.Value.(*ast.StructLit); ok { 102 for i := range s.Elts { 103 if subField, ok := s.Elts[i].(*ast.Field); ok { 104 module := stringValue(subField.Label) 105 version := stringValue(subField.Value) 106 107 if module != "" && version != "" { 108 cg := ast.Comments(subField) 109 110 // require: xxx: xxx 111 if s.Lbrace == token.NoPos { 112 cg = ast.Comments(subField) 113 } 114 115 m.comments[directive+"://"+module] = cg 116 117 r := Requirement{} 118 119 vv := strings.Split(version, "#") 120 if len(vv) > 1 { 121 r.VcsRef = "" 122 } 123 r.Version = vv[0] 124 125 for _, attr := range subField.Attrs { 126 k, v := attr.Split() 127 128 switch k { 129 case "vcs": 130 // TODO remove in future 131 value, _ := strconv.Unquote(v) 132 r.VcsRef = value 133 case "indirect": 134 r.Indirect = true 135 } 136 } 137 138 m.Require[module] = r 139 } 140 } 141 } 142 } 143 } 144 } 145 } 146 } 147 148 return true, nil 149 } 150 151 return false, nil 152 } 153 154 func stringValue(node ast.Node) string { 155 switch v := node.(type) { 156 case *ast.Ident: 157 return v.Name 158 case *ast.BasicLit: 159 switch v.Kind { 160 case token.STRING: 161 s, _ := strconv.Unquote(v.Value) 162 return s 163 case token.INT, token.FLOAT, token.FALSE, token.TRUE: 164 return v.Value 165 } 166 } 167 168 return "" 169 }