github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/dsref/rev.go (about)

     1  // Package dsref defines structure and syntax for referring to a dataset
     2  package dsref
     3  
     4  import (
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  )
     9  
    10  // Rev names a field of a dataset at a snapshot relative to the latest version
    11  // in a history
    12  // Much of this is inspired by git revisions:
    13  // https://git-scm.com/docs/gitrevisions
    14  //
    15  // Unlike git, Qri is aware of the underlying data model it's selecting against,
    16  // so revisions can have conventional names for specifying fields of a dataset
    17  type Rev struct {
    18  	// field scopt, currently can only be a component name, or the entire dataset
    19  	Field string
    20  	// the nth-generational ancestor of a history
    21  	Gen int
    22  }
    23  
    24  // AllGenerations represents all the generations of a dataset's history
    25  const AllGenerations = -1
    26  
    27  // ParseRevs turns a comma-separated list of revisions into a slice of revisions
    28  func ParseRevs(str string) (revs []*Rev, err error) {
    29  	if str == "" {
    30  		return []*Rev{}, nil
    31  	}
    32  	for _, revStr := range strings.Split(str, ",") {
    33  		rev, err := ParseRev(revStr)
    34  		if err != nil {
    35  			return nil, err
    36  		}
    37  		revs = append(revs, rev)
    38  	}
    39  	return revs, nil
    40  }
    41  
    42  // ParseRev turns a string into a revision
    43  func ParseRev(rev string) (*Rev, error) {
    44  	// Check for "all".
    45  	if rev == "all" {
    46  		return &Rev{Gen: AllGenerations, Field: "ds"}, nil
    47  	}
    48  	// Check for integer.
    49  	num, err := strconv.Atoi(rev)
    50  	if err == nil {
    51  		return &Rev{Gen: num, Field: "ds"}, nil
    52  	}
    53  	// Check for field name.
    54  	field, ok := fieldMap[rev]
    55  	if ok {
    56  		return &Rev{Gen: 1, Field: field}, nil
    57  	}
    58  	return nil, fmt.Errorf("unrecognized revision field: %s", rev)
    59  }
    60  
    61  // NewAllRevisions returns a Rev struct that represents all revisions.
    62  func NewAllRevisions() *Rev {
    63  	return &Rev{Field: "ds", Gen: AllGenerations}
    64  }
    65  
    66  var fieldMap = map[string]string{
    67  	"dataset":   "ds",
    68  	"meta":      "md",
    69  	"viz":       "vz",
    70  	"transform": "tf",
    71  	"structure": "st",
    72  	"body":      "bd",
    73  	"rendered":  "rd",
    74  	"readme":    "rm",
    75  
    76  	"ds": "ds",
    77  	"md": "md",
    78  	"vz": "vz",
    79  	"tf": "tf",
    80  	"st": "st",
    81  	"bd": "bd",
    82  	"rd": "rd",
    83  	"rm": "rm",
    84  }