github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/cd-service/pkg/event/reader.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  	"errors"
    21  	"fmt"
    22  	fserr "io/fs"
    23  	"reflect"
    24  
    25  	"github.com/go-git/go-billy/v5"
    26  	"github.com/go-git/go-billy/v5/util"
    27  )
    28  
    29  func read(
    30  	filesystem billy.Filesystem,
    31  	dir string,
    32  	val any,
    33  ) error {
    34  	v := reflect.ValueOf(val)
    35  	return readFile(filesystem, dir, v.Elem(), v.Elem().Type(), encodingDefault)
    36  }
    37  
    38  func readFile(
    39  	fs billy.Filesystem,
    40  	file string,
    41  	value reflect.Value,
    42  	tp reflect.Type,
    43  	encoding encoding,
    44  ) error {
    45  	switch tp.Kind() {
    46  	case reflect.Pointer:
    47  		_, err := fs.Stat(file)
    48  		if err != nil {
    49  			if errors.Is(err, fserr.ErrNotExist) {
    50  				return nil
    51  			}
    52  			return err
    53  		}
    54  		if value.IsNil() {
    55  			value.Set(reflect.New(tp.Elem()))
    56  		}
    57  		return readFile(fs, file, value.Elem(), tp.Elem(), encoding)
    58  	case reflect.String:
    59  		cont, err := util.ReadFile(fs, file)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		value.SetString(string(cont))
    64  		return nil
    65  	case reflect.Struct:
    66  		for i := 0; i < tp.NumField(); i++ {
    67  			f := tp.Field(i)
    68  			name, enc := parseTag(f.Tag.Get("fs"))
    69  			if name == "" {
    70  				name = f.Name
    71  			}
    72  			if err := readFile(fs,
    73  				fs.Join(file, name),
    74  				value.Field(i),
    75  				f.Type,
    76  				enc,
    77  			); err != nil {
    78  				return err
    79  			}
    80  		}
    81  		return nil
    82  	case reflect.Map:
    83  		if tp.Key().Kind() != reflect.String {
    84  			return fmt.Errorf("can only use maps with strings as keys")
    85  		}
    86  		files, err := fs.ReadDir(file)
    87  		if err != nil {
    88  			return err
    89  		}
    90  		if value.IsNil() {
    91  			value.Set(reflect.MakeMapWithSize(tp, len(files)))
    92  		}
    93  		for _, sub := range files {
    94  			if sub.Name() == ".gitkeep" {
    95  				continue
    96  			}
    97  			val := reflect.New(tp.Elem()).Elem()
    98  			if err := readFile(fs,
    99  				fs.Join(file, sub.Name()),
   100  				val,
   101  				tp.Elem(),
   102  				encodingDefault,
   103  			); err != nil {
   104  				return err
   105  			}
   106  			value.SetMapIndex(reflect.ValueOf(sub.Name()), val)
   107  		}
   108  		return nil
   109  	default:
   110  		return fmt.Errorf("cannot read type %v", tp)
   111  	}
   112  }