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  }