github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/env/memory.go (about) 1 // Copyright 2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package env 16 17 import ( 18 "context" 19 "fmt" 20 "os" 21 "time" 22 23 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 24 "github.com/dolthub/dolt/go/libraries/doltcore/ref" 25 "github.com/dolthub/dolt/go/libraries/utils/concurrentmap" 26 "github.com/dolthub/dolt/go/libraries/utils/config" 27 "github.com/dolthub/dolt/go/store/chunks" 28 "github.com/dolthub/dolt/go/store/datas" 29 "github.com/dolthub/dolt/go/store/hash" 30 ) 31 32 func NewMemoryDbData(ctx context.Context, cfg config.ReadableConfig) (DbData, error) { 33 branchName := GetDefaultInitBranch(cfg) 34 35 ddb, err := NewMemoryDoltDB(ctx, branchName) 36 if err != nil { 37 return DbData{}, err 38 } 39 40 rs, err := NewMemoryRepoState(ctx, ddb, branchName) 41 if err != nil { 42 return DbData{}, err 43 } 44 45 return DbData{ 46 Ddb: ddb, 47 Rsw: rs, 48 Rsr: rs, 49 }, nil 50 } 51 52 func NewMemoryDoltDB(ctx context.Context, initBranch string) (*doltdb.DoltDB, error) { 53 ts := &chunks.TestStorage{} 54 cs := ts.NewViewWithDefaultFormat() 55 ddb := doltdb.DoltDBFromCS(cs) 56 57 m := "memory" 58 branchRef := ref.NewBranchRef(initBranch) 59 err := ddb.WriteEmptyRepoWithCommitTimeAndDefaultBranch(ctx, m, m, datas.CommitterDate(), branchRef) 60 if err != nil { 61 return nil, err 62 } 63 64 return ddb, nil 65 } 66 67 func NewMemoryRepoState(ctx context.Context, ddb *doltdb.DoltDB, initBranch string) (MemoryRepoState, error) { 68 head := ref.NewBranchRef(initBranch) 69 rs := MemoryRepoState{ 70 DoltDB: ddb, 71 Head: head, 72 } 73 74 commit, err := ddb.ResolveCommitRef(ctx, head) 75 if err != nil { 76 return MemoryRepoState{}, err 77 } 78 79 root, err := commit.GetRootValue(ctx) 80 if err != nil { 81 return MemoryRepoState{}, err 82 } 83 84 err = rs.UpdateWorkingRoot(ctx, root) 85 if err != nil { 86 return MemoryRepoState{}, err 87 } 88 89 err = rs.UpdateStagedRoot(ctx, root) 90 if err != nil { 91 return MemoryRepoState{}, err 92 } 93 94 return rs, nil 95 } 96 97 type MemoryRepoState struct { 98 DoltDB *doltdb.DoltDB 99 Head ref.DoltRef 100 } 101 102 var _ RepoStateReader = MemoryRepoState{} 103 var _ RepoStateWriter = MemoryRepoState{} 104 105 func (m MemoryRepoState) CWBHeadRef() (ref.DoltRef, error) { 106 return m.Head, nil 107 } 108 109 func (m MemoryRepoState) CWBHeadSpec() (*doltdb.CommitSpec, error) { 110 headRef, err := m.CWBHeadRef() 111 if err != nil { 112 return nil, err 113 } 114 spec, err := doltdb.NewCommitSpec(headRef.GetPath()) 115 if err != nil { 116 return nil, err 117 } 118 return spec, nil 119 } 120 121 func (m MemoryRepoState) UpdateStagedRoot(ctx context.Context, newRoot doltdb.RootValue) error { 122 var h hash.Hash 123 var wsRef ref.WorkingSetRef 124 125 ws, err := m.WorkingSet(ctx) 126 if err == doltdb.ErrWorkingSetNotFound { 127 // first time updating root 128 headRef, err := m.CWBHeadRef() 129 if err != nil { 130 return err 131 } 132 wsRef, err = ref.WorkingSetRefForHead(headRef) 133 if err != nil { 134 return err 135 } 136 ws = doltdb.EmptyWorkingSet(wsRef).WithWorkingRoot(newRoot).WithStagedRoot(newRoot) 137 } else if err != nil { 138 return err 139 } else { 140 h, err = ws.HashOf() 141 if err != nil { 142 return err 143 } 144 145 wsRef = ws.Ref() 146 } 147 148 return m.DoltDB.UpdateWorkingSet(ctx, wsRef, ws.WithStagedRoot(newRoot), h, m.workingSetMeta(), nil) 149 } 150 151 func (m MemoryRepoState) UpdateWorkingRoot(ctx context.Context, newRoot doltdb.RootValue) error { 152 var h hash.Hash 153 var wsRef ref.WorkingSetRef 154 155 ws, err := m.WorkingSet(ctx) 156 if err == doltdb.ErrWorkingSetNotFound { 157 // first time updating root 158 headRef, err := m.CWBHeadRef() 159 if err != nil { 160 return err 161 } 162 wsRef, err = ref.WorkingSetRefForHead(headRef) 163 if err != nil { 164 return err 165 } 166 ws = doltdb.EmptyWorkingSet(wsRef).WithWorkingRoot(newRoot).WithStagedRoot(newRoot) 167 } else if err != nil { 168 return err 169 } else { 170 h, err = ws.HashOf() 171 if err != nil { 172 return err 173 } 174 175 wsRef = ws.Ref() 176 } 177 178 return m.DoltDB.UpdateWorkingSet(ctx, wsRef, ws.WithWorkingRoot(newRoot), h, m.workingSetMeta(), nil) 179 } 180 181 func (m MemoryRepoState) WorkingSet(ctx context.Context) (*doltdb.WorkingSet, error) { 182 headRef, err := m.CWBHeadRef() 183 if err != nil { 184 return nil, err 185 } 186 workingSetRef, err := ref.WorkingSetRefForHead(headRef) 187 if err != nil { 188 return nil, err 189 } 190 191 workingSet, err := m.DoltDB.ResolveWorkingSet(ctx, workingSetRef) 192 if err != nil { 193 return nil, err 194 } 195 196 return workingSet, nil 197 } 198 199 func (m MemoryRepoState) workingSetMeta() *datas.WorkingSetMeta { 200 return &datas.WorkingSetMeta{ 201 Timestamp: uint64(time.Now().Unix()), 202 Description: "updated from dolt environment", 203 } 204 } 205 206 func (m MemoryRepoState) SetCWBHeadRef(_ context.Context, r ref.MarshalableRef) (err error) { 207 m.Head = r.Ref 208 return 209 } 210 211 func (m MemoryRepoState) GetRemotes() (*concurrentmap.Map[string, Remote], error) { 212 return concurrentmap.New[string, Remote](), nil 213 } 214 215 func (m MemoryRepoState) AddRemote(r Remote) error { 216 return fmt.Errorf("cannot insert a remote in a memory database") 217 } 218 219 func (m MemoryRepoState) GetBranches() (*concurrentmap.Map[string, BranchConfig], error) { 220 return concurrentmap.New[string, BranchConfig](), nil 221 } 222 223 func (m MemoryRepoState) UpdateBranch(name string, new BranchConfig) error { 224 return nil 225 } 226 227 func (m MemoryRepoState) RemoveRemote(ctx context.Context, name string) error { 228 return fmt.Errorf("cannot delete a remote from a memory database") 229 } 230 231 func (m MemoryRepoState) TempTableFilesDir() (string, error) { 232 return os.TempDir(), nil 233 } 234 235 func (m MemoryRepoState) GetBackups() (*concurrentmap.Map[string, Remote], error) { 236 panic("cannot get backups on in memory database") 237 } 238 239 func (m MemoryRepoState) AddBackup(r Remote) error { 240 panic("cannot add backup to in memory database") 241 } 242 243 func (m MemoryRepoState) RemoveBackup(ctx context.Context, name string) error { 244 panic("cannot remove backup from in memory database") 245 }