github.com/benchkram/bob@v0.0.0-20240314204020-b7a57f2f9be9/pkg/buildinfostore/protostore.go (about)

     1  package buildinfostore
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/benchkram/bob/bobtask/buildinfo"
    10  	"github.com/benchkram/bob/bobtask/buildinfo/protos"
    11  	"github.com/benchkram/bob/pkg/file"
    12  	"github.com/benchkram/errz"
    13  
    14  	"google.golang.org/protobuf/proto"
    15  )
    16  
    17  type ps struct {
    18  	dir string
    19  }
    20  
    21  // NewProtoStore creates a proto store. The caller is responsible to pass an existing directory
    22  func NewProtoStore(dir string) Store {
    23  	return &ps{dir: dir}
    24  }
    25  
    26  // NewBuildInfo creates a new build info file.
    27  func (ps *ps) NewBuildInfo(id string, info *buildinfo.I) (err error) {
    28  	defer errz.Recover(&err)
    29  
    30  	m := info.ToProto(id)
    31  
    32  	b, err := proto.Marshal(m)
    33  	errz.Fatal(err)
    34  
    35  	err = os.WriteFile(filepath.Join(ps.dir, id), b, 0666)
    36  	errz.Fatal(err)
    37  
    38  	return nil
    39  }
    40  
    41  // GetArtifact opens a file
    42  func (ps *ps) GetBuildInfo(id string) (info *buildinfo.I, err error) {
    43  	defer errz.Recover(&err)
    44  
    45  	f, err := os.Open(filepath.Join(ps.dir, id))
    46  	if err != nil {
    47  		return nil, ErrBuildInfoDoesNotExist
    48  	}
    49  	errz.Fatal(err)
    50  	defer f.Close()
    51  
    52  	b, err := io.ReadAll(f)
    53  	errz.Fatal(err)
    54  
    55  	protoInfo := &protos.BuildInfo{}
    56  
    57  	err = proto.Unmarshal(b, protoInfo)
    58  	errz.Fatal(err)
    59  
    60  	if !isValid(protoInfo) {
    61  		return nil, ErrBuildInfoInvalid
    62  	}
    63  
    64  	return buildinfo.FromProto(protoInfo), nil
    65  }
    66  
    67  func (ps *ps) GetBuildInfos() (_ []*buildinfo.I, err error) {
    68  	defer errz.Recover(&err)
    69  
    70  	entries, err := os.ReadDir(ps.dir)
    71  	errz.Fatal(err)
    72  
    73  	var buildInfos []*buildinfo.I
    74  	for _, entry := range entries {
    75  		if entry.IsDir() {
    76  			continue
    77  		}
    78  
    79  		data, err := os.ReadFile(filepath.Join(ps.dir, entry.Name()))
    80  		errz.Fatal(err)
    81  
    82  		bi := &protos.BuildInfo{}
    83  		err = proto.Unmarshal(data, bi)
    84  		errz.Fatal(err)
    85  
    86  		if !isValid(bi) {
    87  			return nil, ErrBuildInfoInvalid
    88  		}
    89  
    90  		buildInfos = append(buildInfos, buildinfo.FromProto(bi))
    91  	}
    92  
    93  	return buildInfos, nil
    94  }
    95  
    96  func isValid(bi *protos.BuildInfo) bool {
    97  	return bi.Meta != nil
    98  }
    99  
   100  func (ps *ps) Clean() (err error) {
   101  	defer errz.Recover(&err)
   102  
   103  	homeDir, err := os.UserHomeDir()
   104  	errz.Fatal(err)
   105  	if ps.dir == "/" || ps.dir == homeDir {
   106  		return fmt.Errorf("Cleanup of %s is not allowed", ps.dir)
   107  	}
   108  
   109  	entrys, err := os.ReadDir(ps.dir)
   110  	errz.Fatal(err)
   111  
   112  	for _, entry := range entrys {
   113  		if entry.IsDir() {
   114  			continue
   115  		}
   116  		_ = os.Remove(filepath.Join(ps.dir, entry.Name()))
   117  	}
   118  
   119  	return nil
   120  }
   121  
   122  func (ps *ps) BuildInfoExists(id string) bool {
   123  	return file.Exists(filepath.Join(ps.dir, id))
   124  }