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