github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/cd-service/pkg/event/writer.go (about) 1 /*This file is part of kuberpult. 2 3 Kuberpult is free software: you can redistribute it and/or modify 4 it under the terms of the Expat(MIT) License as published by 5 the Free Software Foundation. 6 7 Kuberpult is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 MIT License for more details. 11 12 You should have received a copy of the MIT License 13 along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>. 14 15 Copyright 2023 freiheit.com*/ 16 17 package event 18 19 import ( 20 "fmt" 21 "reflect" 22 "strings" 23 24 "github.com/go-git/go-billy/v5" 25 "github.com/go-git/go-billy/v5/util" 26 ) 27 28 func write( 29 filesystem billy.Filesystem, 30 dir string, 31 val any, 32 ) error { 33 return writeFile(filesystem, dir, reflect.ValueOf(val), encodingDefault) 34 } 35 36 func writeFile( 37 fs billy.Filesystem, 38 file string, 39 value reflect.Value, 40 encoding encoding, 41 ) error { 42 tp := value.Type() 43 switch tp.Kind() { 44 case reflect.Pointer: 45 if value.IsNil() { 46 return nil 47 } 48 return writeFile(fs, file, value.Elem(), encoding) 49 case reflect.String: 50 val := value.Interface().(string) 51 return util.WriteFile(fs, file, []byte(val), 0666) 52 case reflect.Struct: 53 if err := fs.MkdirAll(file, 0777); err != nil { 54 return err 55 } 56 if tp.NumField() == 0 { 57 return util.WriteFile(fs, fs.Join(file, ".gitkeep"), []byte{}, 0666) 58 } 59 for i := 0; i < tp.NumField(); i++ { 60 f := tp.Field(i) 61 name, enc := parseTag(f.Tag.Get("fs")) 62 if name == "" { 63 name = f.Name 64 } 65 if err := writeFile(fs, 66 fs.Join(file, name), 67 value.Field(i), 68 enc, 69 ); err != nil { 70 return err 71 } 72 } 73 return nil 74 case reflect.Map: 75 if tp.Key().Kind() != reflect.String { 76 return fmt.Errorf("can only use maps with strings as keys") 77 } 78 if err := fs.MkdirAll(file, 0777); err != nil { 79 return err 80 } 81 if value.Len() == 0 { 82 return util.WriteFile(fs, fs.Join(file, ".gitkeep"), []byte{}, 0666) 83 } 84 iter := value.MapRange() 85 for iter.Next() { 86 fileName := iter.Key().Interface().(string) 87 if err := writeFile(fs, 88 fs.Join(file, fileName), 89 iter.Value(), 90 encodingDefault, 91 ); err != nil { 92 return err 93 } 94 } 95 return nil 96 case reflect.Slice: 97 if err := fs.MkdirAll(file, 0777); err != nil { 98 return err 99 } 100 if value.Len() == 0 { 101 return util.WriteFile(fs, fs.Join(file, ".gitkeep"), []byte{}, 0666) 102 } 103 for i := 0; i < value.Len(); i++ { 104 if err := writeFile(fs, 105 fs.Join(file, fmt.Sprintf("%d", i)), 106 value.Index(i), 107 encodingDefault, 108 ); err != nil { 109 return err 110 } 111 } 112 return nil 113 default: 114 return fmt.Errorf("cannot write type %v", tp) 115 } 116 } 117 118 type encoding int 119 120 const ( 121 encodingDefault encoding = iota 122 ) 123 124 func parseTag(tag string) (name string, encoding encoding) { 125 elems := strings.Split(tag, ",") 126 if len(elems) == 0 { 127 return "", encodingDefault 128 } 129 name = elems[0] 130 if len(elems) == 1 { 131 return name, encodingDefault 132 } 133 switch elems[1] { 134 case "default", "": 135 encoding = encodingDefault 136 default: 137 panic(fmt.Sprintf("unknown encoding: %q", elems[1])) 138 } 139 return name, encoding 140 }