Starting to rip out regular expression code for refs / paths

This commit is contained in:
Zach Musgrave
2022-08-18 15:07:08 -07:00
parent 309afd40db
commit 5aac031a69
15 changed files with 80 additions and 98 deletions

View File

@@ -216,7 +216,7 @@ func (ddb *DoltDB) WriteEmptyRepoWithCommitTimeAndDefaultBranch(
}
func getCommitValForRefStr(ctx context.Context, db datas.Database, vrw types.ValueReadWriter, ref string) (*datas.Commit, error) {
if !datas.DatasetFullRe.MatchString(ref) {
if err := datas.ValidateDatasetId(ref); err != nil {
return nil, fmt.Errorf("invalid ref format: %s", ref)
}

View File

@@ -40,12 +40,8 @@ import (
)
var commands = []*util.Command{
nomsCommit,
nomsConfig,
nomsDiff,
nomsDs,
nomsLog,
nomsMerge,
nomsRoot,
nomsShow,
nomsSync,

0
go/store/cmd/noms/noms_commit.go Normal file → Executable file
View File

0
go/store/cmd/noms/noms_commit_test.go Normal file → Executable file
View File

0
go/store/cmd/noms/noms_diff.go Normal file → Executable file
View File

0
go/store/cmd/noms/noms_diff_test.go Normal file → Executable file
View File

16
go/store/cmd/noms/noms_log.go Normal file → Executable file
View File

@@ -24,7 +24,6 @@ package main
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"math"
@@ -412,17 +411,4 @@ func min(i, j int) int {
return i
}
return j
}
func locationFromTimezoneArg(tz string, defaultTZ *time.Location) (*time.Location, error) {
switch tz {
case "local":
return time.Local, nil
case "utc":
return time.UTC, nil
case "":
return defaultTZ, nil
default:
return nil, errors.New("value must be: local or utc")
}
}
}

18
go/store/cmd/noms/noms_log_test.go Normal file → Executable file
View File

@@ -28,7 +28,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/dolthub/dolt/go/store/d"
"github.com/dolthub/dolt/go/store/datas"
"github.com/dolthub/dolt/go/store/hash"
"github.com/dolthub/dolt/go/store/spec"
@@ -127,23 +126,6 @@ func mustHead(ds datas.Dataset) types.Value {
return s
}
func mustHeadAddr(ds datas.Dataset) hash.Hash {
addr, ok := ds.MaybeHeadAddr()
d.PanicIfFalse(ok)
return addr
}
func mustHeadValue(ds datas.Dataset) types.Value {
val, ok, err := ds.MaybeHeadValue()
d.PanicIfError(err)
if !ok {
panic("no head")
}
return val
}
func (s *nomsLogTestSuite) TestNArg() {
dsName := "nArgTest"

0
go/store/cmd/noms/noms_merge.go Normal file → Executable file
View File

0
go/store/cmd/noms/noms_merge_test.go Normal file → Executable file
View File

View File

@@ -24,9 +24,11 @@ package main
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"os"
"time"
flag "github.com/juju/gnuflag"
@@ -211,3 +213,16 @@ func outputEncodedValue(ctx context.Context, w io.Writer, value types.Value) err
return types.WriteEncodedValue(ctx, w, value)
}
}
func locationFromTimezoneArg(tz string, defaultTZ *time.Location) (*time.Location, error) {
switch tz {
case "local":
return time.Local, nil
case "utc":
return time.UTC, nil
case "":
return defaultTZ, nil
default:
return nil, errors.New("value must be: local or utc")
}
}

View File

@@ -25,6 +25,8 @@ import (
"context"
"testing"
"github.com/dolthub/dolt/go/store/d"
"github.com/dolthub/dolt/go/store/hash"
"github.com/stretchr/testify/suite"
"github.com/dolthub/dolt/go/libraries/utils/file"
@@ -208,3 +210,20 @@ func (s *nomsSyncTestSuite) TestRewind() {
s.True(types.Float(42).Equals(mustHeadValue(dest)))
db.Close()
}
func mustHeadValue(ds datas.Dataset) types.Value {
val, ok, err := ds.MaybeHeadValue()
d.PanicIfError(err)
if !ok {
panic("no head")
}
return val
}
func mustHeadAddr(ds datas.Dataset) hash.Hash {
addr, ok := ds.MaybeHeadAddr()
d.PanicIfFalse(ok)
return addr
}

View File

@@ -25,7 +25,6 @@ import (
"context"
"errors"
"fmt"
"regexp"
"strings"
"unicode"
@@ -34,11 +33,6 @@ import (
"github.com/dolthub/dolt/go/store/types"
)
// DatasetRe is a regexp that matches a legal Dataset name anywhere within the target string.
// This regular expression isn't enough by itself, additional patterns are forbidden as well.
// See ValidateDatasetId.
var DatasetRe = regexp.MustCompile(`[^\:\?\[\\\^~ \t\*/]+`)
type refnameAction byte
const (
refnameOk refnameAction = 0
@@ -48,6 +42,39 @@ const (
refnameIllegal refnameAction = 4
)
// ValidateDatasetId returns ErrInvalidDatasetID if the given dataset ID is invalid
func ValidateDatasetId(refname string) error {
var componentCount int
if refname == "@" {
// Refname is a single character '@'.
return ErrInvalidDatasetID
}
if strings.HasSuffix(refname, "/") || strings.HasSuffix(refname, ".") {
return ErrInvalidDatasetID
}
for len(refname) > 0 {
componentLen, err := validateDatasetIdComponent(refname)
if err != nil {
return err
}
componentCount++
// Next component
refname = refname[componentLen:]
}
// if componentCount < 2 {
// // Refname has only one component
// return ErrInvalidDatasetID
// }
return nil
}
// How to handle various characters in refnames:
// 0: An acceptable character for refs
// 1: End-of-component
@@ -120,42 +147,6 @@ func validateDatasetIdComponent(refname string) (int, error) {
return numChars, nil
}
func ValidateDatasetId(refname string) error {
var componentCount int
if refname == "@" {
// Refname is a single character '@'.
return ErrInvalidDatasetID
}
if strings.HasSuffix(refname, "/") || strings.HasSuffix(refname, ".") {
return ErrInvalidDatasetID
}
for len(refname) > 0 {
componentLen, err := validateDatasetIdComponent(refname)
if err != nil {
return err
}
componentCount++
// Next component
refname = refname[componentLen:]
}
if componentCount < 2 {
// Refname has only one component
return ErrInvalidDatasetID
}
return nil
}
// DatasetFullRe is a regexp that matches a only a target string that is
// entirely legal Dataset name.
var DatasetFullRe = regexp.MustCompile("^" + DatasetRe.String() + "$")
type WorkingSetHead struct {
Meta *WorkingSetMeta
WorkingAddr hash.Hash
@@ -636,10 +627,6 @@ func (ds Dataset) MaybeHeadValue() (types.Value, bool, error) {
return nil, false, nil
}
func IsValidDatasetName(name string) bool {
return DatasetFullRe.MatchString(name)
}
func NewHeadlessDataset(db Database, id string) Dataset {
return Dataset{
id: id,

View File

@@ -228,8 +228,7 @@ func TestHeadValueFunctions(t *testing.T) {
assert.False(ok)
}
func TestIsValidDatasetName(t *testing.T) {
assert := assert.New(t)
func TestValidateDatasetId(t *testing.T) {
cases := []struct {
name string
valid bool
@@ -242,7 +241,13 @@ func TestIsValidDatasetName(t *testing.T) {
{"f!!", false},
}
for _, c := range cases {
assert.Equal(c.valid, IsValidDatasetName(c.name),
"Expected %s validity to be %t", c.name, c.valid)
t.Run(c.name, func(t *testing.T) {
err := ValidateDatasetId(c.name)
if c.valid {
assert.NoError(t, err)
} else {
assert.Error(t, err)
}
})
}
}

12
go/store/spec/absolute_path.go Normal file → Executable file
View File

@@ -25,15 +25,12 @@ import (
"context"
"errors"
"fmt"
"regexp"
"github.com/dolthub/dolt/go/store/datas"
"github.com/dolthub/dolt/go/store/hash"
"github.com/dolthub/dolt/go/store/types"
)
var datasetCapturePrefixRe = regexp.MustCompile("^(" + datas.DatasetRe.String() + ")")
// AbsolutePath describes the location of a Value within a Noms database.
//
// To locate a value relative to some other value, see Path. To locate a value
@@ -79,13 +76,8 @@ func NewAbsolutePath(str string) (AbsolutePath, error) {
pathStr = tail[hash.StringLen:]
} else {
datasetParts := datasetCapturePrefixRe.FindStringSubmatch(str)
if datasetParts == nil {
return AbsolutePath{}, fmt.Errorf("invalid dataset name: %s", str)
}
dataset = datasetParts[1]
pathStr = str[len(dataset):]
dataset = str
pathStr = ""
}
if len(pathStr) == 0 {