diff --git a/cmd/noms/noms_ds_test.go b/cmd/noms/noms_ds_test.go index 463ccedf1c..e3f5ba3531 100644 --- a/cmd/noms/noms_ds_test.go +++ b/cmd/noms/noms_ds_test.go @@ -47,12 +47,12 @@ func (s *nomsDsTestSuite) TestNomsDs() { id := "testdataset" set := dataset.NewDataset(ds, id) - set, err := set.Commit(types.String("Commit Value")) + set, err := set.CommitValue(types.String("Commit Value")) s.NoError(err) id2 := "testdataset2" set2 := dataset.NewDataset(ds, id2) - set2, err = set2.Commit(types.String("Commit Value2")) + set2, err = set2.CommitValue(types.String("Commit Value2")) s.NoError(err) err = ds.Close() diff --git a/cmd/noms/noms_log_test.go b/cmd/noms/noms_log_test.go index e01212bbd7..d15d1347d1 100644 --- a/cmd/noms/noms_log_test.go +++ b/cmd/noms/noms_log_test.go @@ -42,7 +42,7 @@ type nomsLogTestSuite struct { func testCommitInResults(s *nomsLogTestSuite, str string, i int) { ds, err := spec.GetDataset(str) s.NoError(err) - ds, err = ds.Commit(types.Number(i)) + ds, err = ds.CommitValue(types.Number(i)) s.NoError(err) commit := ds.Head() ds.Database().Close() @@ -64,19 +64,21 @@ func (s *nomsLogTestSuite) TestNomsLog() { } func addCommit(ds dataset.Dataset, v string) (dataset.Dataset, error) { - return ds.Commit(types.String(v)) + return ds.CommitValue(types.String(v)) } func addCommitWithValue(ds dataset.Dataset, v types.Value) (dataset.Dataset, error) { - return ds.Commit(v) + return ds.CommitValue(v) } func addBranchedDataset(newDs, parentDs dataset.Dataset, v string) (dataset.Dataset, error) { - return newDs.CommitWithParents(types.String(v), types.NewSet().Insert(parentDs.HeadRef())) + p := types.NewSet(parentDs.HeadRef()) + return newDs.Commit(types.String(v), dataset.CommitOptions{Parents: p}) } func mergeDatasets(ds1, ds2 dataset.Dataset, v string) (dataset.Dataset, error) { - return ds1.CommitWithParents(types.String(v), types.NewSet(ds1.HeadRef(), ds2.HeadRef())) + p := types.NewSet(ds1.HeadRef(), ds2.HeadRef()) + return ds1.Commit(types.String(v), dataset.CommitOptions{Parents: p}) } func (s *nomsLogTestSuite) TestNArg() { diff --git a/cmd/noms/noms_show_test.go b/cmd/noms/noms_show_test.go index 2a312b6604..05df841feb 100644 --- a/cmd/noms/noms_show_test.go +++ b/cmd/noms/noms_show_test.go @@ -35,7 +35,7 @@ func writeTestData(str string, value types.Value) types.Ref { d.Chk.NoError(err) r1 := ds.Database().WriteValue(value) - ds, err = ds.Commit(r1) + ds, err = ds.CommitValue(r1) d.Chk.NoError(err) err = ds.Database().Close() diff --git a/cmd/noms/noms_sync_test.go b/cmd/noms/noms_sync_test.go index 79830b6547..5a68c34bb8 100644 --- a/cmd/noms/noms_sync_test.go +++ b/cmd/noms/noms_sync_test.go @@ -29,7 +29,7 @@ type nomsSyncTestSuite struct { func (s *nomsSyncTestSuite) TestSyncValidation() { source1 := dataset.NewDataset(datas.NewDatabase(chunks.NewLevelDBStore(s.LdbDir, "", 1, false)), "src") - source1, err := source1.Commit(types.Number(42)) + source1, err := source1.CommitValue(types.Number(42)) s.NoError(err) source1HeadRef := source1.Head().Hash() source1.Database().Close() @@ -48,9 +48,9 @@ func (s *nomsSyncTestSuite) TestSyncValidation() { func (s *nomsSyncTestSuite) TestSync() { source1 := dataset.NewDataset(datas.NewDatabase(chunks.NewLevelDBStore(s.LdbDir, "", 1, false)), "foo") - source1, err := source1.Commit(types.Number(42)) + source1, err := source1.CommitValue(types.Number(42)) s.NoError(err) - source2, err := source1.Commit(types.Number(43)) + source2, err := source1.CommitValue(types.Number(43)) s.NoError(err) source1HeadRef := source1.Head().Hash() source2.Database().Close() // Close Database backing both Datasets diff --git a/go/dataset/commit_options.go b/go/dataset/commit_options.go new file mode 100644 index 0000000000..a11ceab783 --- /dev/null +++ b/go/dataset/commit_options.go @@ -0,0 +1,13 @@ +// Copyright 2016 Attic Labs, Inc. All rights reserved. +// Licensed under the Apache License, version 2.0: +// http://www.apache.org/licenses/LICENSE-2.0 + +package dataset + +import "github.com/attic-labs/noms/go/types" + +// CommitOptions is used to pass options into Commit. +type CommitOptions struct { + // Parents, if provided is the parent commits of the commit we are creating. + Parents types.Set +} diff --git a/go/dataset/dataset.go b/go/dataset/dataset.go index 521894194e..9af5606591 100644 --- a/go/dataset/dataset.go +++ b/go/dataset/dataset.go @@ -72,21 +72,25 @@ func (ds *Dataset) MaybeHeadValue() (types.Value, bool) { return c.Get(datas.ValueField), true } -// Commit updates the commit that a dataset points at. The new Commit is constructed using v and the current Head. +// CommitValue updates the commit that a dataset points at. The new Commit struct is constructed using v and the current Head. // If the update cannot be performed, e.g., because of a conflict, Commit returns an 'ErrMergeNeeded' error and the current snapshot of the dataset so that the client can merge the changes and try again. -func (ds *Dataset) Commit(v types.Value) (Dataset, error) { - p := types.NewSet() - if headRef, ok := ds.MaybeHeadRef(); ok { - headRef.TargetValue(ds.Database()) // TODO: This is a hack to deconfuse the validation code, which doesn't hold onto validation state between commits. - p = p.Insert(headRef) - } - return ds.CommitWithParents(v, p) +func (ds *Dataset) CommitValue(v types.Value) (Dataset, error) { + return ds.Commit(v, CommitOptions{}) } -// CommitWithParents updates the commit that a dataset points at. The new Commit is constructed using v and p. -// If the update cannot be performed, e.g., because of a conflict, CommitWithParents returns an 'ErrMergeNeeded' error and the current snapshot of the dataset so that the client can merge the changes and try again. -func (ds *Dataset) CommitWithParents(v types.Value, p types.Set) (Dataset, error) { - newCommit := datas.NewCommit(v, p) +// Commit updates the commit that a dataset points at. The new Commit struct is constructed using `v` and `opts.Parents`. +// If `opts.Parents` is the zero value (`types.Set{}`) then the current head is used. +// If the update cannot be performed, e.g., because of a conflict, CommitWith returns an 'ErrMergeNeeded' error and the current snapshot of the dataset so that the client can merge the changes and try again. +func (ds *Dataset) Commit(v types.Value, opts CommitOptions) (Dataset, error) { + parents := opts.Parents + if (parents == types.Set{}) { + parents = types.NewSet() + if headRef, ok := ds.MaybeHeadRef(); ok { + headRef.TargetValue(ds.Database()) // TODO: This is a hack to deconfuse the validation code, which doesn't hold onto validation state between commits. + parents = parents.Insert(headRef) + } + } + newCommit := datas.NewCommit(v, parents) store, err := ds.Database().Commit(ds.id, newCommit) return Dataset{store, ds.id}, err } @@ -131,5 +135,6 @@ func (ds *Dataset) validateRefAsCommit(r types.Ref) types.Struct { // again using this new Dataset. func (ds *Dataset) setNewHead(newHeadRef types.Ref) (Dataset, error) { commit := ds.validateRefAsCommit(newHeadRef) - return ds.CommitWithParents(commit.Get(datas.ValueField), commit.Get(datas.ParentsField).(types.Set)) + p := commit.Get(datas.ParentsField).(types.Set) + return ds.Commit(commit.Get(datas.ValueField), CommitOptions{Parents: p}) } diff --git a/go/dataset/dataset_test.go b/go/dataset/dataset_test.go index da9d088f8d..c3e5a41d7d 100644 --- a/go/dataset/dataset_test.go +++ b/go/dataset/dataset_test.go @@ -21,12 +21,12 @@ func TestDatasetCommitTracker(t *testing.T) { ds1 := NewDataset(datas.NewDatabase(cs), id1) ds1Commit := types.String("Commit value for " + id1) - ds1, err := ds1.Commit(ds1Commit) + ds1, err := ds1.CommitValue(ds1Commit) assert.NoError(err) ds2 := NewDataset(datas.NewDatabase(cs), id2) ds2Commit := types.String("Commit value for " + id2) - ds2, err = ds2.Commit(ds2Commit) + ds2, err = ds2.CommitValue(ds2Commit) assert.NoError(err) assert.EqualValues(ds1Commit, ds1.Head().Get(datas.ValueField)) @@ -52,27 +52,27 @@ func TestExplicitBranchUsingDatasets(t *testing.T) { // ds1: |a| a := types.String("a") - ds1, err := ds1.Commit(a) + ds1, err := ds1.CommitValue(a) assert.NoError(err) assert.True(ds1.Head().Get(datas.ValueField).Equals(a)) // ds1: |a| // \ds2 ds2 := newDS(id2, cs) - ds2, err = ds2.Commit(ds1.Head().Get(datas.ValueField)) + ds2, err = ds2.CommitValue(ds1.Head().Get(datas.ValueField)) assert.NoError(err) assert.True(ds2.Head().Get(datas.ValueField).Equals(a)) // ds1: |a| <- |b| b := types.String("b") - ds1, err = ds1.Commit(b) + ds1, err = ds1.CommitValue(b) assert.NoError(err) assert.True(ds1.Head().Get(datas.ValueField).Equals(b)) // ds1: |a| <- |b| // \ds2 <- |c| c := types.String("c") - ds2, err = ds2.Commit(c) + ds2, err = ds2.CommitValue(c) assert.NoError(err) assert.True(ds2.Head().Get(datas.ValueField).Equals(c)) @@ -80,11 +80,11 @@ func TestExplicitBranchUsingDatasets(t *testing.T) { // \ds2 <- |c| <--/ mergeParents := types.NewSet(types.NewRef(ds1.Head()), types.NewRef(ds2.Head())) d := types.String("d") - ds2, err = ds2.CommitWithParents(d, mergeParents) + ds2, err = ds2.Commit(d, CommitOptions{Parents: mergeParents}) assert.NoError(err) assert.True(ds2.Head().Get(datas.ValueField).Equals(d)) - ds1, err = ds1.CommitWithParents(d, mergeParents) + ds1, err = ds1.Commit(d, CommitOptions{Parents: mergeParents}) assert.NoError(err) assert.True(ds1.Head().Get(datas.ValueField).Equals(d)) } @@ -99,7 +99,7 @@ func TestTwoClientsWithEmptyDataset(t *testing.T) { // dsx: || -> |a| a := types.String("a") - dsx, err := dsx.Commit(a) + dsx, err := dsx.CommitValue(a) assert.NoError(err) assert.True(dsx.Head().Get(datas.ValueField).Equals(a)) @@ -107,11 +107,11 @@ func TestTwoClientsWithEmptyDataset(t *testing.T) { _, ok := dsy.MaybeHead() assert.False(ok) b := types.String("b") - dsy, err = dsy.Commit(b) + dsy, err = dsy.CommitValue(b) assert.Error(err) // Commit failed, but ds1 now has latest head, so we should be able to just try again. // dsy: |a| -> |b| - dsy, err = dsy.Commit(b) + dsy, err = dsy.CommitValue(b) assert.NoError(err) assert.True(dsy.Head().Get(datas.ValueField).Equals(b)) } @@ -125,7 +125,7 @@ func TestTwoClientsWithNonEmptyDataset(t *testing.T) { { // ds1: || -> |a| ds1 := newDS(id1, cs) - ds1, err := ds1.Commit(a) + ds1, err := ds1.CommitValue(a) assert.NoError(err) assert.True(ds1.Head().Get(datas.ValueField).Equals(a)) } @@ -136,19 +136,19 @@ func TestTwoClientsWithNonEmptyDataset(t *testing.T) { // dsx: |a| -> |b| assert.True(dsx.Head().Get(datas.ValueField).Equals(a)) b := types.String("b") - dsx, err := dsx.Commit(b) + dsx, err := dsx.CommitValue(b) assert.NoError(err) assert.True(dsx.Head().Get(datas.ValueField).Equals(b)) // dsy: |a| -> |c| assert.True(dsy.Head().Get(datas.ValueField).Equals(a)) c := types.String("c") - dsy, err = dsy.Commit(c) + dsy, err = dsy.CommitValue(c) assert.Error(err) assert.True(dsy.Head().Get(datas.ValueField).Equals(b)) // Commit failed, but dsy now has latest head, so we should be able to just try again. // dsy: |b| -> |c| - dsy, err = dsy.Commit(c) + dsy, err = dsy.CommitValue(c) assert.NoError(err) assert.True(dsy.Head().Get(datas.ValueField).Equals(c)) } @@ -176,7 +176,7 @@ func TestHeadValueFunctions(t *testing.T) { // ds1: |a| a := types.String("a") - ds1, err := ds1.Commit(a) + ds1, err := ds1.CommitValue(a) assert.NoError(err) hv := ds1.Head().Get(datas.ValueField) diff --git a/go/dataset/pull_test.go b/go/dataset/pull_test.go index 753c39ad6b..81d51ad52d 100644 --- a/go/dataset/pull_test.go +++ b/go/dataset/pull_test.go @@ -56,21 +56,21 @@ func TestPullTopDown(t *testing.T) { types.String("second"), NewList(sink, types.Number(2))) var err error - source, err = source.Commit(sourceInitialValue) + source, err = source.CommitValue(sourceInitialValue) assert.NoError(err) - sink, err = sink.Commit(sinkInitialValue) + sink, err = sink.CommitValue(sinkInitialValue) assert.NoError(err) // Add some new stuff to source. updatedValue := sourceInitialValue.Set( types.String("third"), NewList(source, types.Number(3))) - source, err = source.Commit(updatedValue) + source, err = source.CommitValue(updatedValue) assert.NoError(err) // Add some more stuff, so that source isn't directly ahead of sink. updatedValue = updatedValue.Set( types.String("fourth"), NewList(source, types.Number(4))) - source, err = source.Commit(updatedValue) + source, err = source.CommitValue(updatedValue) assert.NoError(err) sink, err = sink.Pull(source.Database(), types.NewRef(source.Head()), 1, nil) @@ -91,7 +91,7 @@ func TestPullFirstCommitTopDown(t *testing.T) { NewList(sink) NewList(sink, types.Number(2)) - source, err := source.Commit(sourceInitialValue) + source, err := source.CommitValue(sourceInitialValue) assert.NoError(err) sink, err = sink.Pull(source.Database(), types.NewRef(source.Head()), 1, nil) @@ -110,7 +110,7 @@ func TestPullDeepRefTopDown(t *testing.T) { types.NewSet(NewSet(source)), types.NewMap(NewMap(source), NewMap(source))) - source, err := source.Commit(sourceInitialValue) + source, err := source.CommitValue(sourceInitialValue) assert.NoError(err) sink, err = sink.Pull(source.Database(), types.NewRef(source.Head()), 1, nil) diff --git a/go/perf/codec-perf-rig/main.go b/go/perf/codec-perf-rig/main.go index 9f87975bdb..11381b46d6 100644 --- a/go/perf/codec-perf-rig/main.go +++ b/go/perf/codec-perf-rig/main.go @@ -59,7 +59,7 @@ func main() { ds := dataset.NewDataset(datas.NewDatabase(ms), "test") t1 := time.Now() col := buildFns[i](buildCount, valueFn) - ds, err := ds.Commit(col) + ds, err := ds.CommitValue(col) d.Chk.NoError(err) buildDuration := time.Since(t1) @@ -74,7 +74,7 @@ func main() { ds = dataset.NewDataset(datas.NewDatabase(ms), "test") t1 = time.Now() col = buildIncrFns[i](insertCount, valueFn) - ds, err = ds.Commit(col) + ds, err = ds.CommitValue(col) d.Chk.NoError(err) incrDuration := time.Since(t1) @@ -95,7 +95,7 @@ func main() { blobBytes := makeBlobBytes(*blobSize) t1 := time.Now() blob := types.NewBlob(bytes.NewReader(blobBytes)) - ds.Commit(blob) + ds.CommitValue(blob) buildDuration := time.Since(t1) ds = dataset.NewDataset(datas.NewDatabase(ms), "test") diff --git a/go/spec/dataspec_test.go b/go/spec/dataspec_test.go index 727348ddbb..7f18855800 100644 --- a/go/spec/dataspec_test.go +++ b/go/spec/dataspec_test.go @@ -67,7 +67,7 @@ func TestMemDataset(t *testing.T) { dataset1, err := sp1.Dataset() assert.NoError(err) commit := types.String("Commit Value") - dsTest, err := dataset1.Commit(commit) + dsTest, err := dataset1.CommitValue(commit) assert.NoError(err) assert.EqualValues(commit, dsTest.HeadValue()) } @@ -84,7 +84,7 @@ func TestLDBDataset(t *testing.T) { set := dataset.NewDataset(ds, id) commit := types.String("Commit Value") - set, err = set.Commit(commit) + set, err = set.CommitValue(commit) assert.NoError(err) ds.Close() @@ -110,7 +110,7 @@ func TestLDBObject(t *testing.T) { dataset1 := dataset.NewDataset(store1, dsId) s1 := types.String("Commit Value") r1 := store1.WriteValue(s1) - _, err = dataset1.Commit(r1) + _, err = dataset1.CommitValue(r1) assert.NoError(err) store1.Close() @@ -146,7 +146,7 @@ func TestReadHash(t *testing.T) { database1 := datas.NewDatabase(cs1) dataset1 := dataset.NewDataset(database1, datasetId) commit := types.String("Commit Value") - dataset1, err = dataset1.Commit(commit) + dataset1, err = dataset1.CommitValue(commit) assert.NoError(err) r1 := dataset1.Head().Hash() dataset1.Database().Close() diff --git a/samples/go/counter/counter.go b/samples/go/counter/counter.go index 24ce477b25..784343479d 100644 --- a/samples/go/counter/counter.go +++ b/samples/go/counter/counter.go @@ -40,7 +40,7 @@ func main() { newVal = uint64(lastVal.(types.Number)) + 1 } - _, err = ds.Commit(types.Number(newVal)) + _, err = ds.CommitValue(types.Number(newVal)) if err != nil { fmt.Fprintf(os.Stderr, "Error committing: %s\n", err) return diff --git a/samples/go/csv/csv-export/exporter_test.go b/samples/go/csv/csv-export/exporter_test.go index bf923d36ab..f61c9e9487 100644 --- a/samples/go/csv/csv-export/exporter_test.go +++ b/samples/go/csv/csv-export/exporter_test.go @@ -57,7 +57,7 @@ func (s *testSuite) TestCSVExporter() { structs[i] = types.NewStructWithType(typ, fields) } - ds.Commit(types.NewList(structs...)) + ds.CommitValue(types.NewList(structs...)) ds.Database().Close() // Run exporter diff --git a/samples/go/csv/csv-import/importer.go b/samples/go/csv/csv-import/importer.go index dbce57aad4..5728485f3e 100644 --- a/samples/go/csv/csv-import/importer.go +++ b/samples/go/csv/csv-import/importer.go @@ -145,7 +145,7 @@ func main() { } else { value = csv.ReadToMap(cr, headers, pk, kinds, ds.Database()) } - _, err = ds.Commit(value) + _, err = ds.CommitValue(value) if !*noProgress { status.Clear() } diff --git a/samples/go/csv/csv-import/importer_test.go b/samples/go/csv/csv-import/importer_test.go index 1ccb66467f..8b2ff46fdf 100644 --- a/samples/go/csv/csv-import/importer_test.go +++ b/samples/go/csv/csv-import/importer_test.go @@ -85,7 +85,7 @@ func (s *testSuite) TestCSVImporterFromBlob() { rawDS := dataset.NewDataset(db, "raw") csv := &bytes.Buffer{} writeCSV(csv) - rawDS.Commit(types.NewBlob(csv)) + rawDS.CommitValue(types.NewBlob(csv)) db.Close() stdout, stderr := s.Run(main, []string{ diff --git a/samples/go/hr/main.go b/samples/go/hr/main.go index 79dbcc572a..ffe00b452d 100644 --- a/samples/go/hr/main.go +++ b/samples/go/hr/main.go @@ -74,7 +74,7 @@ func addPerson(ds dataset.Dataset) { "title": types.String(flag.Arg(3)), }) - _, err = ds.Commit(getPersons(ds).Set(types.Number(id), np)) + _, err = ds.CommitValue(getPersons(ds).Set(types.Number(id), np)) if err != nil { fmt.Fprintf(os.Stderr, "Error committing: %s\n", err) return diff --git a/samples/go/json-import/json_importer.go b/samples/go/json-import/json_importer.go index a1134206e3..6967edd5fb 100644 --- a/samples/go/json-import/json_importer.go +++ b/samples/go/json-import/json_importer.go @@ -53,7 +53,7 @@ func main() { log.Fatalln("Error decoding JSON: ", err) } - _, err = ds.Commit(jsontonoms.NomsValueFromDecodedJSON(jsonObject, true)) + _, err = ds.CommitValue(jsontonoms.NomsValueFromDecodedJSON(jsonObject, true)) d.PanicIfError(err) ds.Database().Close() } diff --git a/samples/go/url-fetch/fetch.go b/samples/go/url-fetch/fetch.go index 3761f57bb2..d2cf40be4b 100644 --- a/samples/go/url-fetch/fetch.go +++ b/samples/go/url-fetch/fetch.go @@ -81,7 +81,7 @@ func main() { } b := types.NewStreamingBlob(pr, ds.Database()) - ds, err = ds.Commit(b) + ds, err = ds.CommitValue(b) if err != nil { d.Chk.Equal(datas.ErrMergeNeeded, err) fmt.Fprintf(os.Stderr, "Could not commit, optimistic concurrency failed.") diff --git a/samples/go/xml-import/xml_importer.go b/samples/go/xml-import/xml_importer.go index 4bbd154382..2b523ade17 100644 --- a/samples/go/xml-import/xml_importer.go +++ b/samples/go/xml-import/xml_importer.go @@ -135,7 +135,7 @@ func main() { rl := types.NewList(refs...) if !*noIO { - _, err := ds.Commit(rl) + _, err := ds.CommitValue(rl) d.PanicIfError(err) } }) diff --git a/samples/js/counter/integration_test.go b/samples/js/counter/integration_test.go index d0ee6379ad..06a065d1f8 100644 --- a/samples/js/counter/integration_test.go +++ b/samples/js/counter/integration_test.go @@ -26,7 +26,7 @@ func (s *testSuite) Setup() { db := s.Database() defer db.Close() ds := dataset.NewDataset(db, dsName) - _, err := ds.Commit(types.Number(42)) + _, err := ds.CommitValue(types.Number(42)) s.NoError(err) }