github.com/Benchkram/bob@v0.0.0-20220321080157-7c8f3876e225/bob/bob.go (about) 1 package bob 2 3 import ( 4 "io/ioutil" 5 "os" 6 7 "github.com/Benchkram/bob/pkg/usererror" 8 9 "github.com/hashicorp/go-version" 10 11 "gopkg.in/yaml.v3" 12 13 "github.com/Benchkram/errz" 14 15 "github.com/Benchkram/bob/pkg/buildinfostore" 16 "github.com/Benchkram/bob/pkg/file" 17 "github.com/Benchkram/bob/pkg/store" 18 ) 19 20 var Version = "0.0.0" 21 22 type B struct { 23 // Repositories to track. 24 Repositories []Repo `yaml:"repositories"` 25 26 // dir is bob's working directory. 27 dir string 28 29 // local the place to store artifacts localy 30 local store.Store 31 // TODO: add a remote store 32 // remotestore cas.Store 33 34 buildInfoStore buildinfostore.Store 35 36 // readConfig some commands need a fully initialised bob. 37 // When this is true a `.bob.workspace` file must exist, 38 // usually done by calling `bob init` 39 readConfig bool 40 41 // enableCaching allows to save and load artifacts 42 // from the cache Default: true 43 enableCaching bool 44 } 45 46 func newBob(opts ...Option) *B { 47 wd, err := os.Getwd() 48 if err != nil { 49 errz.Fatal(err) 50 } 51 52 b := &B{ 53 dir: wd, 54 enableCaching: true, 55 } 56 57 for _, opt := range opts { 58 if opt == nil { 59 continue 60 } 61 opt(b) 62 } 63 64 return b 65 } 66 67 // BobWithBaseStoreDir initialises stores in the given directory 68 func BobWithBaseStoreDir(baseStoreDir string, opts ...Option) (*B, error) { 69 bob := newBob(opts...) 70 71 _, err := version.NewVersion(Version) 72 if err != nil { 73 return nil, ErrInvalidVersion 74 } 75 76 fs, err := Filestore(baseStoreDir) 77 if err != nil { 78 return nil, err 79 } 80 bob.local = fs 81 82 bis, err := BuildinfoStore(baseStoreDir) 83 if err != nil { 84 return nil, err 85 } 86 bob.buildInfoStore = bis 87 88 for _, opt := range opts { 89 if opt == nil { 90 continue 91 } 92 opt(bob) 93 } 94 95 return bob, nil 96 } 97 98 func Bob(opts ...Option) (*B, error) { 99 bob := newBob(opts...) 100 101 _, err := version.NewVersion(Version) 102 if err != nil { 103 return nil, ErrInvalidVersion 104 } 105 106 if bob.readConfig { 107 err := bob.read() 108 if err != nil { 109 return nil, err 110 } 111 } 112 113 if bob.local == nil { 114 fs, err := DefaultFilestore() 115 if err != nil { 116 return nil, err 117 } 118 bob.local = fs 119 } 120 121 if bob.buildInfoStore == nil { 122 bis, err := DefaultBuildinfoStore() 123 if err != nil { 124 return nil, err 125 } 126 bob.buildInfoStore = bis 127 } 128 129 return bob, nil 130 } 131 132 func (b *B) Dir() string { 133 return b.dir 134 } 135 136 func (b *B) write() (err error) { 137 defer errz.Recover(&err) 138 139 bin, err := yaml.Marshal(b) 140 errz.Fatal(err) 141 142 const mode = 0644 143 return ioutil.WriteFile(b.WorkspaceFilePath(), bin, mode) 144 } 145 146 func (b *B) read() (err error) { 147 defer errz.Recover(&err) 148 149 if !file.Exists(b.WorkspaceFilePath()) { 150 // Initialise with default values if it does not exist. 151 err := b.write() 152 errz.Fatal(err) 153 } 154 155 bin, err := ioutil.ReadFile(b.WorkspaceFilePath()) 156 errz.Fatal(err, "Failed to read config file") 157 158 err = yaml.Unmarshal(bin, b) 159 if err != nil { 160 return usererror.Wrapm(err, "YAML unmarshal failed") 161 } 162 163 return nil 164 }