github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/projectfile/yamlfield.go (about) 1 package projectfile 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "regexp" 8 9 "github.com/ActiveState/cli/internal/errs" 10 "gopkg.in/yaml.v2" 11 ) 12 13 type yamlField struct { 14 field string 15 value interface{} 16 } 17 18 func NewYamlField(field string, value interface{}) *yamlField { 19 return &yamlField{field: field, value: value} 20 } 21 22 func (y *yamlField) update(data []byte) ([]byte, error) { 23 lineSep := []byte("\n") 24 if bytes.Contains(data, []byte("\r\n")) { 25 lineSep = []byte("\r\n") 26 } 27 28 var re = regexp.MustCompile(fmt.Sprintf(`(?m:^%s:\s+?(.*?)$)`, regexp.QuoteMeta(y.field))) 29 addLine, err := yaml.Marshal(map[string]interface{}{y.field: y.value}) 30 if err != nil { 31 return []byte{}, errs.Wrap(err, "Could not marshal yaml") 32 } 33 34 addLine = bytes.TrimRight(addLine, string(lineSep)) 35 36 out := re.ReplaceAll(data, addLine) 37 if !bytes.Contains(out, addLine) { 38 // Nothing to replace; append to the end of the file instead 39 addLine = append(lineSep, addLine...) // Prepend line ending 40 addLine = append(addLine, lineSep...) // Append line ending 41 out = append(bytes.TrimRight(out, string(lineSep)), addLine...) 42 } 43 44 return out, nil 45 } 46 47 func (y *yamlField) Save(path string) error { 48 data, err := os.ReadFile(path) 49 if err != nil { 50 return errs.Wrap(err, "ioutil.ReadFile %s failed", path) 51 } 52 53 out, err := y.update(data) 54 if err != nil { 55 return errs.Wrap(err, "Update failed") 56 } 57 58 if err := os.WriteFile(path, out, 0664); err != nil { 59 return errs.Wrap(err, "ioutil.WriteFile %s failed", path) 60 } 61 62 return nil 63 }