github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/spec/absolute_path.go (about) 1 // Copyright 2019 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 // This file incorporates work covered by the following copyright and 16 // permission notice: 17 // 18 // Copyright 2016 Attic Labs, Inc. All rights reserved. 19 // Licensed under the Apache License, version 2.0: 20 // http://www.apache.org/licenses/LICENSE-2.0 21 22 package spec 23 24 import ( 25 "context" 26 "errors" 27 28 "github.com/dolthub/dolt/go/store/datas" 29 "github.com/dolthub/dolt/go/store/hash" 30 "github.com/dolthub/dolt/go/store/types" 31 ) 32 33 // AbsolutePath describes the location of a Value within a Noms database. 34 // 35 // To locate a value relative to some other value, see Path. To locate a value 36 // globally, see Spec. 37 // 38 // For more on paths, absolute paths, and specs, see: 39 // https://github.com/attic-labs/noms/blob/master/doc/spelling.md. 40 type AbsolutePath struct { 41 // Dataset is the dataset this AbsolutePath is rooted at. Only one of 42 // Dataset and Hash should be set. 43 Dataset string 44 // Hash is the hash this AbsolutePath is rooted at. Only one of Dataset and 45 // Hash should be set. 46 Hash hash.Hash 47 } 48 49 // NewAbsolutePath attempts to parse 'str' and return an AbsolutePath. 50 func NewAbsolutePath(str string) (AbsolutePath, error) { 51 if len(str) == 0 { 52 return AbsolutePath{}, errors.New("empty path") 53 } 54 55 var h hash.Hash 56 var dataset string 57 58 if str[0] == '#' { 59 tail := str[1:] 60 if len(tail) < hash.StringLen { 61 return AbsolutePath{}, errors.New("invalid hash: " + tail) 62 } 63 64 hashStr := tail[:hash.StringLen] 65 if h2, ok := hash.MaybeParse(hashStr); ok { 66 h = h2 67 } else { 68 return AbsolutePath{}, errors.New("invalid hash: " + hashStr) 69 } 70 } else { 71 // This form is only used in the noms command. Commands like `noms show` that use a path with '.' separation will 72 // no longer work 73 dataset = str 74 } 75 76 return AbsolutePath{Hash: h, Dataset: dataset}, nil 77 } 78 79 // Resolve returns the Value reachable by 'p' in 'db'. 80 func (p AbsolutePath) Resolve(ctx context.Context, db datas.Database, vrw types.ValueReadWriter) (val types.Value, err error) { 81 if len(p.Dataset) > 0 { 82 var ok bool 83 ds, err := db.GetDataset(ctx, p.Dataset) 84 if err != nil { 85 return nil, err 86 } 87 88 if val, ok = ds.MaybeHead(); !ok { 89 val = nil 90 } 91 } else if !p.Hash.IsEmpty() { 92 var err error 93 val, err = vrw.ReadValue(ctx, p.Hash) 94 if err != nil { 95 return nil, err 96 } 97 } else { 98 panic("Unreachable") 99 } 100 101 return 102 } 103 104 func (p AbsolutePath) IsEmpty() bool { 105 return p.Dataset == "" && p.Hash.IsEmpty() 106 } 107 108 func (p AbsolutePath) String() (str string) { 109 if p.IsEmpty() { 110 return "" 111 } 112 113 if len(p.Dataset) > 0 { 114 str = p.Dataset 115 } else if !p.Hash.IsEmpty() { 116 str = "#" + p.Hash.String() 117 } else { 118 panic("Unreachable") 119 } 120 121 return str 122 }