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  }