github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/packages/conan/conaninfo_parser.go (about) 1 // Copyright 2023 The GitBundle Inc. All rights reserved. 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file. 5 6 package conan 7 8 import ( 9 "bufio" 10 "errors" 11 "io" 12 "strings" 13 ) 14 15 // Conaninfo represents infos of a Conan package 16 type Conaninfo struct { 17 Settings map[string]string `json:"settings"` 18 FullSettings map[string]string `json:"full_settings"` 19 Requires []string `json:"requires"` 20 FullRequires []string `json:"full_requires"` 21 Options map[string]string `json:"options"` 22 FullOptions map[string]string `json:"full_options"` 23 RecipeHash string `json:"recipe_hash"` 24 Environment map[string][]string `json:"environment"` 25 } 26 27 func ParseConaninfo(r io.Reader) (*Conaninfo, error) { 28 sections, err := readSections(io.LimitReader(r, 1<<20)) 29 if err != nil { 30 return nil, err 31 } 32 33 info := &Conaninfo{} 34 for section, lines := range sections { 35 if len(lines) == 0 { 36 continue 37 } 38 switch section { 39 case "settings": 40 info.Settings = toMap(lines) 41 case "full_settings": 42 info.FullSettings = toMap(lines) 43 case "options": 44 info.Options = toMap(lines) 45 case "full_options": 46 info.FullOptions = toMap(lines) 47 case "requires": 48 info.Requires = lines 49 case "full_requires": 50 info.FullRequires = lines 51 case "recipe_hash": 52 info.RecipeHash = lines[0] 53 case "env": 54 info.Environment = toMapArray(lines) 55 } 56 } 57 return info, nil 58 } 59 60 func readSections(r io.Reader) (map[string][]string, error) { 61 sections := make(map[string][]string) 62 63 section := "" 64 lines := make([]string, 0, 5) 65 66 scanner := bufio.NewScanner(r) 67 for scanner.Scan() { 68 line := strings.TrimSpace(scanner.Text()) 69 if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { 70 if section != "" { 71 sections[section] = lines 72 } 73 section = line[1 : len(line)-1] 74 lines = make([]string, 0, 5) 75 continue 76 } 77 if section != "" { 78 if line != "" { 79 lines = append(lines, line) 80 } 81 continue 82 } 83 if line != "" { 84 return nil, errors.New("Invalid conaninfo.txt") 85 } 86 } 87 if err := scanner.Err(); err != nil { 88 return nil, err 89 } 90 if section != "" { 91 sections[section] = lines 92 } 93 return sections, nil 94 } 95 96 func toMap(lines []string) map[string]string { 97 result := make(map[string]string) 98 for _, line := range lines { 99 parts := strings.SplitN(line, "=", 2) 100 if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 { 101 continue 102 } 103 result[parts[0]] = parts[1] 104 } 105 return result 106 } 107 108 func toMapArray(lines []string) map[string][]string { 109 result := make(map[string][]string) 110 for _, line := range lines { 111 parts := strings.SplitN(line, "=", 2) 112 if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 { 113 continue 114 } 115 var items []string 116 if strings.HasPrefix(parts[1], "[") && strings.HasSuffix(parts[1], "]") { 117 items = strings.Split(parts[1], ",") 118 } else { 119 items = []string{parts[1]} 120 } 121 result[parts[0]] = items 122 } 123 return result 124 }