mirror of
https://github.com/dolthub/dolt.git
synced 2026-04-28 04:28:53 -05:00
Vinai/refactor docs (#1210)
This pr does a massive refactor of the internal state management with docs.
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@ teardown() {
|
||||
teardown_common
|
||||
}
|
||||
|
||||
@test "dolt status and ls to view valid docs on dolt init" {
|
||||
@test "dolt status and ls to view supported docs on dolt init" {
|
||||
echo license-text > LICENSE.md
|
||||
echo readme-text > README.md
|
||||
run ls
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
|
||||
eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env/actions"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
|
||||
@@ -121,7 +122,7 @@ func (cmd CheckoutCmd) Exec(ctx context.Context, commandStr string, args []strin
|
||||
return HandleVErrAndExitCode(verr, usagePrt)
|
||||
}
|
||||
|
||||
tbls, docs, err := actions.GetTblsAndDocDetails(dEnv.DocsReadWriter(), args)
|
||||
tbls, docs, err := actions.GetTablesOrDocs(dEnv.DocsReadWriter(), args)
|
||||
if err != nil {
|
||||
verr := errhand.BuildDError("error: unable to parse arguments.").AddCause(err).Build()
|
||||
return HandleVErrAndExitCode(verr, usagePrt)
|
||||
@@ -189,7 +190,7 @@ func checkoutNewBranch(ctx context.Context, dEnv *env.DoltEnv, newBranch string,
|
||||
return checkoutBranch(ctx, dEnv, newBranch)
|
||||
}
|
||||
|
||||
func checkoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, tables []string, docs []doltdb.DocDetails) errhand.VerboseError {
|
||||
func checkoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, tables []string, docs doltdocs.Docs) errhand.VerboseError {
|
||||
err := actions.CheckoutTablesAndDocs(ctx, dEnv, tables, docs)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/diff"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env/actions"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
@@ -244,7 +245,7 @@ func parseDiffArgs(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgPar
|
||||
dArgs.docSet = set.NewStrSet(nil)
|
||||
|
||||
for _, arg := range leftover {
|
||||
if arg == doltdb.ReadmePk || arg == doltdb.LicensePk {
|
||||
if arg == doltdocs.ReadmeDoc || arg == doltdocs.LicenseDoc {
|
||||
dArgs.docSet.Add(arg)
|
||||
continue
|
||||
}
|
||||
@@ -275,7 +276,7 @@ func parseDiffArgs(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgPar
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
dArgs.tableSet.Add(utn...)
|
||||
dArgs.docSet.Add(doltdb.ReadmePk, doltdb.LicensePk)
|
||||
dArgs.docSet.Add(doltdocs.ReadmeDoc, doltdocs.LicenseDoc)
|
||||
}
|
||||
|
||||
return from, to, dArgs, nil
|
||||
@@ -283,7 +284,21 @@ func parseDiffArgs(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgPar
|
||||
|
||||
func getDiffRoots(ctx context.Context, dEnv *env.DoltEnv, args []string) (from, to *doltdb.RootValue, leftover []string, err error) {
|
||||
headRoot, err := dEnv.StagedRoot(ctx)
|
||||
workingRoot, err := dEnv.WorkingRootWithDocs(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
workingRoot, err := dEnv.WorkingRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
docs, err := dEnv.DocsReadWriter().GetDocsOnDisk()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
workingRoot, err = doltdocs.UpdateRootWithDocs(ctx, workingRoot, docs)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@@ -876,59 +891,45 @@ func createSplitter(ctx context.Context, vrw types.ValueReadWriter, fromSch sche
|
||||
}
|
||||
|
||||
func diffDoltDocs(ctx context.Context, dEnv *env.DoltEnv, from, to *doltdb.RootValue, dArgs *diffArgs) error {
|
||||
_, docDetails, err := actions.GetTblsAndDocDetails(dEnv.DocsReadWriter(), dArgs.docSet.AsSlice())
|
||||
_, docs, err := actions.GetTablesOrDocs(dEnv.DocsReadWriter(), dArgs.docSet.AsSlice())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromDocTable, _, err := from.GetTable(ctx, doltdb.DocTableName)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
toDocTable, _, err := to.GetTable(ctx, doltdb.DocTableName)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printDocDiffs(ctx, dEnv, fromDocTable, toDocTable, docDetails)
|
||||
return nil
|
||||
return printDocDiffs(ctx, from, to, docs)
|
||||
}
|
||||
|
||||
func printDocDiffs(ctx context.Context, dEnv *env.DoltEnv, fromTbl, toTbl *doltdb.Table, docDetails []doltdb.DocDetails) {
|
||||
func printDocDiffs(ctx context.Context, from, to *doltdb.RootValue, docsFilter doltdocs.Docs) error {
|
||||
bold := color.New(color.Bold)
|
||||
|
||||
if docDetails == nil {
|
||||
docDetails, _ = dEnv.GetAllValidDocDetails()
|
||||
comparisons, err := diff.DocsDiffToComparisons(ctx, from, to, docsFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, doc := range docDetails {
|
||||
if toTbl != nil {
|
||||
sch1, _ := toTbl.GetSchema(ctx)
|
||||
doc, _ = doltdb.AddNewerTextToDocFromTbl(ctx, toTbl, &sch1, doc)
|
||||
for _, doc := range docsFilter {
|
||||
for _, comparison := range comparisons {
|
||||
if doc.DocPk == comparison.DocName {
|
||||
if comparison.OldText == nil && comparison.CurrentText != nil {
|
||||
printAddedDoc(bold, comparison.DocName)
|
||||
} else if comparison.OldText != nil {
|
||||
older := string(comparison.OldText)
|
||||
newer := string(comparison.CurrentText)
|
||||
|
||||
}
|
||||
if fromTbl != nil {
|
||||
sch2, _ := fromTbl.GetSchema(ctx)
|
||||
doc, _ = doltdb.AddValueToDocFromTbl(ctx, fromTbl, &sch2, doc)
|
||||
}
|
||||
lines := textdiff.LineDiffAsLines(older, newer)
|
||||
|
||||
if doc.Value != nil {
|
||||
newer := string(doc.NewerText)
|
||||
older, _ := strconv.Unquote(doc.Value.HumanReadableString())
|
||||
lines := textdiff.LineDiffAsLines(older, newer)
|
||||
if doc.NewerText == nil {
|
||||
printDeletedDoc(bold, doc.DocPk, lines)
|
||||
} else if len(lines) > 0 && newer != older {
|
||||
printModifiedDoc(bold, doc.DocPk, lines)
|
||||
if comparison.CurrentText == nil {
|
||||
printDeletedDoc(bold, comparison.DocName, lines)
|
||||
} else if len(lines) > 0 && newer != older {
|
||||
printModifiedDoc(bold, comparison.DocName, lines)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if doc.Value == nil && doc.NewerText != nil {
|
||||
printAddedDoc(bold, doc.DocPk)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printDiffLines(bold *color.Color, lines []string) {
|
||||
|
||||
@@ -322,7 +322,7 @@ func executeFFMerge(ctx context.Context, squash bool, dEnv *env.DoltEnv, cm2 *do
|
||||
}
|
||||
}
|
||||
|
||||
unstagedDocs, err := actions.GetUnstagedDocs(ctx, dEnv)
|
||||
unstagedDocs, err := actions.GetUnstagedDocs(ctx, dEnv.DbData())
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: unable to determine unstaged docs").AddCause(err).Build()
|
||||
}
|
||||
@@ -401,7 +401,7 @@ func mergedRootToWorking(ctx context.Context, squash bool, dEnv *env.DoltEnv, me
|
||||
}
|
||||
}
|
||||
|
||||
unstagedDocs, err := actions.GetUnstagedDocs(ctx, dEnv)
|
||||
unstagedDocs, err := actions.GetUnstagedDocs(ctx, dEnv.DbData())
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: failed to determine unstaged docs").AddCause(err).Build()
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func (cmd ResetCmd) Exec(ctx context.Context, commandStr string, args []string,
|
||||
} else if apr.Contains(HardResetParam) {
|
||||
err = actions.ResetHard(ctx, dEnv, apr, workingRoot, stagedRoot, headRoot)
|
||||
} else {
|
||||
stagedRoot, err = actions.ResetSoft(ctx, dEnv, apr, stagedRoot, headRoot)
|
||||
stagedRoot, err = actions.ResetSoft(ctx, dEnv.DbData(), apr, stagedRoot, headRoot)
|
||||
|
||||
if err != nil {
|
||||
return handleResetError(err, usage)
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package diff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema/encoding"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
func TestDocDiff(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ddb, _ := doltdb.LoadDoltDB(ctx, types.Format_7_18, doltdb.InMemDoltDB)
|
||||
ddb.WriteEmptyRepo(ctx, "billy bob", "bigbillieb@fake.horse")
|
||||
|
||||
cs, _ := doltdb.NewCommitSpec("master")
|
||||
cm, _ := ddb.Resolve(ctx, cs, nil)
|
||||
|
||||
root, err := cm.GetRootValue()
|
||||
assert.NoError(t, err)
|
||||
|
||||
docs := doltdocs.Docs{
|
||||
{DocPk: doltdocs.LicenseDoc},
|
||||
{DocPk: doltdocs.ReadmeDoc},
|
||||
}
|
||||
|
||||
// DocsDiff between a root and itself should return no added, modified or removed docs.
|
||||
added, modified, removed, err := DocsDiff(ctx, root, root, docs)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(added)+len(modified)+len(removed) != 0 {
|
||||
t.Error("Bad doc diff when comparing two repos")
|
||||
}
|
||||
|
||||
// Create tbl1 with one license row
|
||||
sch := createTestDocsSchema()
|
||||
licRow := makeDocRow(t, sch, doltdocs.LicenseDoc, types.String("license row"))
|
||||
m, _ := createTestRows(t, ddb.ValueReadWriter(), sch, []row.Row{licRow})
|
||||
tbl1, err := CreateTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create root2 with tbl1 on it (one doc: license)
|
||||
root2, err := root.PutTable(ctx, doltdb.DocTableName, tbl1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// DocsDiff between root and root2 should return one added doc, LICENSE.md
|
||||
added, modified, removed, err = DocsDiff(ctx, root, root2, docs)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(added) != 1 || added[0] != "LICENSE.md" || len(modified)+len(removed) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
|
||||
// Create tbl2 with one readme row
|
||||
readmeRow := makeDocRow(t, sch, doltdocs.ReadmeDoc, types.String("readme row"))
|
||||
m, _ = createTestRows(t, ddb.ValueReadWriter(), sch, []row.Row{readmeRow})
|
||||
tbl2, err := CreateTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create root3 with tbl2 on it (one doc: readme)
|
||||
root3, err := root.PutTable(ctx, doltdb.DocTableName, tbl2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// DocsDiff between root2 and root3 should return one removed doc (license) and one added doc (readme).
|
||||
added, modified, removed, err = DocsDiff(ctx, root2, root3, docs)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(removed) != 1 || removed[0] != "LICENSE.md" || len(added) != 1 || added[0] != "README.md" || len(modified) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
|
||||
// Create tbl3 with 2 doc rows (readme, license)
|
||||
readmeRowUpdated := makeDocRow(t, sch, doltdocs.ReadmeDoc, types.String("a different readme"))
|
||||
m, _ = createTestRows(t, ddb.ValueReadWriter(), sch, []row.Row{readmeRowUpdated, licRow})
|
||||
tbl3, err := CreateTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create root4 with tbl3 on it (two docs: readme and license)
|
||||
root4, err := root3.PutTable(ctx, doltdb.DocTableName, tbl3)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// DocsDiff between root3 and root4 should return one added doc (license) and one modified doc (readme).
|
||||
added, modified, removed, err = DocsDiff(ctx, root3, root4, nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(added) != 1 || added[0] != "LICENSE.md" || len(modified) != 1 || modified[0] != "README.md" || len(removed) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
|
||||
// DocsDiff between root4 and root shows 2 remove docs (license, readme)
|
||||
added, modified, removed, err = DocsDiff(ctx, root4, root, nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(removed) != 2 || len(modified) != 0 || len(added) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
}
|
||||
|
||||
func CreateTestTable(vrw types.ValueReadWriter, tSchema schema.Schema, rowData types.Map) (*doltdb.Table, error) {
|
||||
schemaVal, err := encoding.MarshalSchemaAsNomsValue(context.Background(), vrw, tSchema)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
empty, _ := types.NewMap(context.Background(), vrw)
|
||||
tbl, err := doltdb.NewTable(context.Background(), vrw, schemaVal, rowData, empty)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tbl, nil
|
||||
}
|
||||
|
||||
func createTestDocsSchema() schema.Schema {
|
||||
typedColColl, _ := schema.NewColCollection(
|
||||
schema.NewColumn(doltdb.DocPkColumnName, schema.DocNameTag, types.StringKind, true, schema.NotNullConstraint{}),
|
||||
schema.NewColumn(doltdb.DocTextColumnName, schema.DocTextTag, types.StringKind, false),
|
||||
)
|
||||
sch, err := schema.SchemaFromCols(typedColColl)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return sch
|
||||
}
|
||||
|
||||
func makeDocRow(t *testing.T, sch schema.Schema, pk string, rowVal types.Value) row.Row {
|
||||
row, err := row.New(types.Format_7_18, sch, row.TaggedValues{
|
||||
schema.DocNameTag: types.String(pk),
|
||||
schema.DocTextTag: rowVal,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
return row
|
||||
}
|
||||
|
||||
func createTestRows(t *testing.T, vrw types.ValueReadWriter, sch schema.Schema, rows []row.Row) (types.Map, []row.Row) {
|
||||
ctx := context.Background()
|
||||
var err error
|
||||
|
||||
m, err := types.NewMap(ctx, vrw)
|
||||
assert.NoError(t, err)
|
||||
ed := m.Edit()
|
||||
|
||||
for _, r := range rows {
|
||||
ed = ed.Set(r.NomsMapKey(sch), r.NomsMapValue(sch))
|
||||
}
|
||||
|
||||
m, err = ed.Map(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return m, rows
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package diff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
)
|
||||
|
||||
type docComparison struct {
|
||||
DocName string
|
||||
CurrentText []byte
|
||||
OldText []byte
|
||||
}
|
||||
|
||||
// DocsDiff returns the added, modified and removed docs when comparing a root value with an other (newer) value. If the other value,
|
||||
// is not provided, then we compare the docs on the root value to the docs provided.
|
||||
func DocsDiff(ctx context.Context, root *doltdb.RootValue, other *doltdb.RootValue, docs doltdocs.Docs) (added, modified, removed []string, err error) {
|
||||
docComparisons, err := DocsDiffToComparisons(ctx, root, other, docs)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
a, m, r := computeDiffsFromDocComparisons(docComparisons)
|
||||
return a, m, r, nil
|
||||
}
|
||||
|
||||
// DocsDiffToComparisons returns the docComparisons between an old root, a new root, and a set of docs. It is exported
|
||||
// due to the cli usage of doc diffs.
|
||||
func DocsDiffToComparisons(ctx context.Context, root *doltdb.RootValue, other *doltdb.RootValue, docs doltdocs.Docs) ([]docComparison, error) {
|
||||
if other == nil {
|
||||
return compareRootWithDocs(ctx, root, docs)
|
||||
} else {
|
||||
return compareDocsBtwnRoots(ctx, root, other)
|
||||
}
|
||||
}
|
||||
|
||||
// compareRootWithDocs compares a root and set of new docs.
|
||||
func compareRootWithDocs(ctx context.Context, root *doltdb.RootValue, docs doltdocs.Docs) ([]docComparison, error) {
|
||||
oldDocs, found, err := doltdocs.GetAllDocs(ctx, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !found {
|
||||
oldDocs = make(doltdocs.Docs, 0)
|
||||
}
|
||||
|
||||
return getDocComparisons(oldDocs, docs), nil
|
||||
}
|
||||
|
||||
// compareDocsBtwnRoots takes an oldRoot and a newRoot and compares the docs tables between the two.
|
||||
func compareDocsBtwnRoots(ctx context.Context, oldRoot *doltdb.RootValue, newRoot *doltdb.RootValue) ([]docComparison, error) {
|
||||
oldDocs, found, err := doltdocs.GetAllDocs(ctx, oldRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !found {
|
||||
oldDocs = make(doltdocs.Docs, 0)
|
||||
}
|
||||
|
||||
newDocs, found, err := doltdocs.GetAllDocs(ctx, newRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !found {
|
||||
newDocs = make(doltdocs.Docs, 0)
|
||||
}
|
||||
|
||||
return getDocComparisons(oldDocs, newDocs), nil
|
||||
}
|
||||
|
||||
// getDocComparisons compares two sets of docs looking for modifications, removals, and additions as docComparisons
|
||||
func getDocComparisons(oldDocs doltdocs.Docs, newDocs doltdocs.Docs) []docComparison {
|
||||
docComparisons := make([]docComparison, 0)
|
||||
|
||||
// First case is looking at the old docs and seeing what was modified or removed
|
||||
for _, oldDoc := range oldDocs {
|
||||
dc := docComparison{DocName: oldDoc.DocPk, OldText: oldDoc.Text, CurrentText: getMatchingText(oldDoc, newDocs)}
|
||||
docComparisons = append(docComparisons, dc)
|
||||
}
|
||||
|
||||
// Second case is looking back at the old docs and seeing what was added
|
||||
for _, newDoc := range newDocs {
|
||||
oldText := getMatchingText(newDoc, oldDocs)
|
||||
if oldText == nil {
|
||||
dc := docComparison{DocName: newDoc.DocPk, OldText: nil, CurrentText: newDoc.Text}
|
||||
docComparisons = append(docComparisons, dc)
|
||||
}
|
||||
}
|
||||
|
||||
return docComparisons
|
||||
}
|
||||
|
||||
// getMatchingText matches a doc in a set of other docs and returns the relevant text.
|
||||
func getMatchingText(doc doltdocs.Doc, docs doltdocs.Docs) []byte {
|
||||
for _, toCompare := range docs {
|
||||
if doc.DocPk == toCompare.DocPk {
|
||||
return toCompare.Text
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// computeDiffsFromDocComparisons takes the docComparisons and returns the final add, modified, removed count.
|
||||
func computeDiffsFromDocComparisons(docComparisons []docComparison) (added, modified, removed []string) {
|
||||
added = []string{}
|
||||
modified = []string{}
|
||||
removed = []string{}
|
||||
for _, doc := range docComparisons {
|
||||
added, modified, removed = appendDocDiffs(added, modified, removed, doc.OldText, doc.CurrentText, doc.DocName)
|
||||
}
|
||||
return added, modified, removed
|
||||
}
|
||||
|
||||
func appendDocDiffs(added, modified, removed []string, olderVal []byte, newerVal []byte, docPk string) (add, mod, rem []string) {
|
||||
if olderVal == nil && newerVal != nil {
|
||||
added = append(added, docPk)
|
||||
} else if olderVal != nil {
|
||||
if newerVal == nil {
|
||||
removed = append(removed, docPk)
|
||||
} else if strconv.Quote(string(olderVal)) != strconv.Quote(string(newerVal)) {
|
||||
modified = append(modified, docPk)
|
||||
}
|
||||
}
|
||||
return added, modified, removed
|
||||
}
|
||||
@@ -19,11 +19,12 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/utils/set"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/set"
|
||||
"github.com/dolthub/dolt/go/store/hash"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
@@ -88,13 +89,13 @@ func (rvu RootValueUnreadable) Error() string {
|
||||
}
|
||||
|
||||
// NewDocDiffs returns DocDiffs for Dolt Docs between two roots.
|
||||
func NewDocDiffs(ctx context.Context, older *doltdb.RootValue, newer *doltdb.RootValue, docDetails []doltdb.DocDetails) (*DocDiffs, error) {
|
||||
func NewDocDiffs(ctx context.Context, older *doltdb.RootValue, newer *doltdb.RootValue, docs doltdocs.Docs) (*DocDiffs, error) {
|
||||
var added []string
|
||||
var modified []string
|
||||
var removed []string
|
||||
if older != nil {
|
||||
if newer == nil {
|
||||
a, m, r, err := older.DocDiff(ctx, nil, docDetails)
|
||||
a, m, r, err := DocsDiff(ctx, older, nil, docs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -102,7 +103,7 @@ func NewDocDiffs(ctx context.Context, older *doltdb.RootValue, newer *doltdb.Roo
|
||||
modified = m
|
||||
removed = r
|
||||
} else {
|
||||
a, m, r, err := older.DocDiff(ctx, newer, docDetails)
|
||||
a, m, r, err := DocsDiff(ctx, older, newer, docs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -111,11 +112,11 @@ func NewDocDiffs(ctx context.Context, older *doltdb.RootValue, newer *doltdb.Roo
|
||||
removed = r
|
||||
}
|
||||
}
|
||||
var docs []string
|
||||
docs = append(docs, added...)
|
||||
docs = append(docs, modified...)
|
||||
docs = append(docs, removed...)
|
||||
sort.Strings(docs)
|
||||
var docNames []string
|
||||
docNames = append(docNames, added...)
|
||||
docNames = append(docNames, modified...)
|
||||
docNames = append(docNames, removed...)
|
||||
sort.Strings(docNames)
|
||||
|
||||
docsToType := make(map[string]DocDiffType)
|
||||
for _, nt := range added {
|
||||
@@ -130,7 +131,7 @@ func NewDocDiffs(ctx context.Context, older *doltdb.RootValue, newer *doltdb.Roo
|
||||
docsToType[nt] = RemovedDoc
|
||||
}
|
||||
|
||||
return &DocDiffs{len(added), len(modified), len(removed), docsToType, docs}, nil
|
||||
return &DocDiffs{len(added), len(modified), len(removed), docsToType, docNames}, nil
|
||||
}
|
||||
|
||||
// Len returns the number of docs in a DocDiffs
|
||||
@@ -140,7 +141,7 @@ func (nd *DocDiffs) Len() int {
|
||||
|
||||
// GetDocDiffs retrieves staged and unstaged DocDiffs.
|
||||
func GetDocDiffs(ctx context.Context, ddb *doltdb.DoltDB, rsr env.RepoStateReader, drw env.DocsReadWriter) (*DocDiffs, *DocDiffs, error) {
|
||||
docDetails, err := drw.GetAllValidDocDetails()
|
||||
docsOnDisk, err := drw.GetDocsOnDisk()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -150,7 +151,7 @@ func GetDocDiffs(ctx context.Context, ddb *doltdb.DoltDB, rsr env.RepoStateReade
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
notStagedDocDiffs, err := NewDocDiffs(ctx, workingRoot, nil, docDetails)
|
||||
notStagedDocDiffs, err := NewDocDiffs(ctx, workingRoot, nil, docsOnDisk)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -165,7 +166,7 @@ func GetDocDiffs(ctx context.Context, ddb *doltdb.DoltDB, rsr env.RepoStateReade
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
stagedDocDiffs, err := NewDocDiffs(ctx, headRoot, stagedRoot, docDetails)
|
||||
stagedDocDiffs, err := NewDocDiffs(ctx, headRoot, stagedRoot, docsOnDisk)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2019 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package doltcore contains the packages for storing, and manipulating versioned data in dolt.
|
||||
package doltcore
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2019 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package doltdb provides a specific schema on top of noms and provides methods and objects for interacting with data
|
||||
// stored in this schema.
|
||||
package doltdb
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package doltdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
func DocTblKeyFromName(fmt *types.NomsBinFormat, name string) (types.Tuple, error) {
|
||||
return types.NewTuple(fmt, types.Uint(schema.DocNameTag), types.String(name))
|
||||
}
|
||||
|
||||
func getDocRow(ctx context.Context, docTbl *Table, sch schema.Schema, key types.Tuple) (r row.Row, ok bool, err error) {
|
||||
rowMap, err := docTbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
var fields types.Value
|
||||
fields, ok, err = rowMap.MaybeGet(ctx, key)
|
||||
if err != nil || !ok {
|
||||
return nil, ok, err
|
||||
}
|
||||
|
||||
r, err = row.FromNoms(sch, key, fields.(types.Tuple))
|
||||
return
|
||||
}
|
||||
@@ -69,7 +69,7 @@ func createTestSchema(t *testing.T) schema.Schema {
|
||||
return sch
|
||||
}
|
||||
|
||||
func createTestTable(vrw types.ValueReadWriter, tSchema schema.Schema, rowData types.Map) (*Table, error) {
|
||||
func CreateTestTable(vrw types.ValueReadWriter, tSchema schema.Schema, rowData types.Map) (*Table, error) {
|
||||
schemaVal, err := encoding.MarshalSchemaAsNomsValue(context.Background(), vrw, tSchema)
|
||||
|
||||
if err != nil {
|
||||
@@ -290,7 +290,7 @@ func TestLDNoms(t *testing.T) {
|
||||
|
||||
tSchema := createTestSchema(t)
|
||||
rowData, _ := createTestRowData(t, ddb.db, tSchema)
|
||||
tbl, err = createTestTable(ddb.db, tSchema, rowData)
|
||||
tbl, err = CreateTestTable(ddb.db, tSchema, rowData)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create test table with data")
|
||||
|
||||
@@ -18,10 +18,8 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema/encoding"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/set"
|
||||
@@ -45,13 +43,6 @@ type RootValue struct {
|
||||
fkc *ForeignKeyCollection // cache the first load
|
||||
}
|
||||
|
||||
type DocDetails struct {
|
||||
NewerText []byte
|
||||
DocPk string
|
||||
Value types.Value
|
||||
File string
|
||||
}
|
||||
|
||||
func NewRootValue(ctx context.Context, vrw types.ValueReadWriter, tables map[string]hash.Hash, ssMap types.Map, fkMap types.Map) (*RootValue, error) {
|
||||
values := make([]types.Value, 2*len(tables))
|
||||
|
||||
@@ -1024,54 +1015,6 @@ func (root *RootValue) RemoveTables(ctx context.Context, tables ...string) (*Roo
|
||||
return newRoot.PutForeignKeyCollection(ctx, fkc)
|
||||
}
|
||||
|
||||
// DocDiff returns the added, modified and removed docs when comparing a root value with an other (newer) value. If the other value,
|
||||
// is not provided, then we compare the docs on the root value to the docDetails provided.
|
||||
func (root *RootValue) DocDiff(ctx context.Context, other *RootValue, docDetails []DocDetails) (added, modified, removed []string, err error) {
|
||||
oldTbl, oldTblFound, err := root.GetTable(ctx, DocTableName)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
var oldSch schema.Schema
|
||||
if oldTblFound {
|
||||
sch, err := oldTbl.GetSchema(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
oldSch = sch
|
||||
}
|
||||
|
||||
if other == nil {
|
||||
detailsWithValues, err := addValuesToDocs(ctx, oldTbl, &oldSch, docDetails)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
a, m, r := GetDocDiffsFromDocDetails(ctx, detailsWithValues)
|
||||
return a, m, r, nil
|
||||
}
|
||||
|
||||
newTbl, newTblFound, err := other.GetTable(ctx, DocTableName)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
var newSch schema.Schema
|
||||
if newTblFound {
|
||||
sch, err := newTbl.GetSchema(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
newSch = sch
|
||||
}
|
||||
|
||||
docDetailsBtwnRoots, err := getDocDetailsBtwnRoots(ctx, newTbl, newSch, newTblFound, oldTbl, oldSch, oldTblFound)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
a, m, r := GetDocDiffsFromDocDetails(ctx, docDetailsBtwnRoots)
|
||||
return a, m, r, nil
|
||||
}
|
||||
|
||||
// GetForeignKeyCollection returns the ForeignKeyCollection for this root. As collections are meant to be modified
|
||||
// in-place, each returned collection may freely be altered without affecting future returned collections from this root.
|
||||
func (root *RootValue) GetForeignKeyCollection(ctx context.Context) (*ForeignKeyCollection, error) {
|
||||
@@ -1176,189 +1119,6 @@ func (root *RootValue) ValidateForeignKeys(ctx context.Context) (*RootValue, err
|
||||
return root.PutForeignKeyCollection(ctx, fkCollection)
|
||||
}
|
||||
|
||||
func getDocDetailsBtwnRoots(ctx context.Context, newTbl *Table, newSch schema.Schema, newTblFound bool, oldTbl *Table, oldSch schema.Schema, oldTblFound bool) ([]DocDetails, error) {
|
||||
var docDetailsBtwnRoots []DocDetails
|
||||
if newTblFound {
|
||||
newRows, err := newTbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = newRows.IterAll(ctx, func(key, val types.Value) error {
|
||||
newRow, err := row.FromNoms(newSch, key.(types.Tuple), val.(types.Tuple))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
doc := DocDetails{}
|
||||
updated, err := addDocPKToDocFromRow(newRow, &doc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updated, err = addNewerTextToDocFromRow(ctx, newRow, &updated)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updated, err = AddValueToDocFromTbl(ctx, oldTbl, &oldSch, updated)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
docDetailsBtwnRoots = append(docDetailsBtwnRoots, updated)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if oldTblFound {
|
||||
oldRows, err := oldTbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = oldRows.IterAll(ctx, func(key, val types.Value) error {
|
||||
oldRow, err := row.FromNoms(oldSch, key.(types.Tuple), val.(types.Tuple))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
doc := DocDetails{}
|
||||
updated, err := addDocPKToDocFromRow(oldRow, &doc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updated, err = AddValueToDocFromTbl(ctx, oldTbl, &oldSch, updated)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updated, err = AddNewerTextToDocFromTbl(ctx, newTbl, &newSch, updated)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if updated.Value != nil && updated.NewerText == nil {
|
||||
docDetailsBtwnRoots = append(docDetailsBtwnRoots, updated)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return docDetailsBtwnRoots, nil
|
||||
}
|
||||
|
||||
func GetDocDiffsFromDocDetails(ctx context.Context, docDetails []DocDetails) (added, modified, removed []string) {
|
||||
added = []string{}
|
||||
modified = []string{}
|
||||
removed = []string{}
|
||||
for _, doc := range docDetails {
|
||||
added, modified, removed = appendDocDiffs(added, modified, removed, doc.Value, doc.NewerText, doc.DocPk)
|
||||
}
|
||||
return added, modified, removed
|
||||
}
|
||||
|
||||
func addValuesToDocs(ctx context.Context, tbl *Table, sch *schema.Schema, docDetails []DocDetails) ([]DocDetails, error) {
|
||||
if tbl != nil && sch != nil {
|
||||
for i, details := range docDetails {
|
||||
newDetails, err := AddValueToDocFromTbl(ctx, tbl, sch, details)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docDetails[i] = newDetails
|
||||
}
|
||||
}
|
||||
return docDetails, nil
|
||||
}
|
||||
|
||||
// AddValueToDocFromTbl updates the Value field of a docDetail using the provided table and schema.
|
||||
func AddValueToDocFromTbl(ctx context.Context, tbl *Table, sch *schema.Schema, docDetail DocDetails) (DocDetails, error) {
|
||||
if tbl != nil && sch != nil {
|
||||
key, err := DocTblKeyFromName(tbl.Format(), docDetail.DocPk)
|
||||
if err != nil {
|
||||
return DocDetails{}, err
|
||||
}
|
||||
|
||||
docRow, ok, err := getDocRow(ctx, tbl, *sch, key)
|
||||
if err != nil {
|
||||
return DocDetails{}, err
|
||||
}
|
||||
|
||||
if ok {
|
||||
docValue, _ := docRow.GetColVal(schema.DocTextTag)
|
||||
docDetail.Value = docValue
|
||||
} else {
|
||||
docDetail.Value = nil
|
||||
}
|
||||
} else {
|
||||
docDetail.Value = nil
|
||||
}
|
||||
return docDetail, nil
|
||||
}
|
||||
|
||||
// AddNewerTextToDocFromTbl updates the NewerText field of a docDetail using the provided table and schema.
|
||||
func AddNewerTextToDocFromTbl(ctx context.Context, tbl *Table, sch *schema.Schema, doc DocDetails) (DocDetails, error) {
|
||||
if tbl != nil && sch != nil {
|
||||
key, err := DocTblKeyFromName(tbl.Format(), doc.DocPk)
|
||||
if err != nil {
|
||||
return DocDetails{}, err
|
||||
}
|
||||
|
||||
docRow, ok, err := getDocRow(ctx, tbl, *sch, key)
|
||||
if err != nil {
|
||||
return DocDetails{}, err
|
||||
}
|
||||
if ok {
|
||||
docValue, _ := docRow.GetColVal(schema.DocTextTag)
|
||||
doc.NewerText = []byte(docValue.(types.String))
|
||||
} else {
|
||||
doc.NewerText = nil
|
||||
}
|
||||
} else {
|
||||
doc.NewerText = nil
|
||||
}
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
func addNewerTextToDocFromRow(ctx context.Context, r row.Row, doc *DocDetails) (DocDetails, error) {
|
||||
docValue, ok := r.GetColVal(schema.DocTextTag)
|
||||
if !ok {
|
||||
doc.NewerText = nil
|
||||
} else {
|
||||
docValStr, err := strconv.Unquote(docValue.HumanReadableString())
|
||||
if err != nil {
|
||||
return DocDetails{}, err
|
||||
}
|
||||
doc.NewerText = []byte(docValStr)
|
||||
}
|
||||
return *doc, nil
|
||||
}
|
||||
|
||||
func addDocPKToDocFromRow(r row.Row, doc *DocDetails) (DocDetails, error) {
|
||||
colVal, _ := r.GetColVal(schema.DocNameTag)
|
||||
if colVal == nil {
|
||||
doc.DocPk = ""
|
||||
} else {
|
||||
docName, err := strconv.Unquote(colVal.HumanReadableString())
|
||||
if err != nil {
|
||||
return DocDetails{}, err
|
||||
}
|
||||
doc.DocPk = docName
|
||||
}
|
||||
|
||||
return *doc, nil
|
||||
}
|
||||
|
||||
func appendDocDiffs(added, modified, removed []string, olderVal types.Value, newerVal []byte, docPk string) (add, mod, rem []string) {
|
||||
if olderVal == nil && newerVal != nil {
|
||||
added = append(added, docPk)
|
||||
} else if olderVal != nil {
|
||||
if newerVal == nil {
|
||||
removed = append(removed, docPk)
|
||||
} else if olderVal.HumanReadableString() != strconv.Quote(string(newerVal)) {
|
||||
modified = append(modified, docPk)
|
||||
}
|
||||
}
|
||||
return added, modified, removed
|
||||
}
|
||||
|
||||
// RootNeedsUniqueTagsMigration determines if this root needs to be migrated to uniquify its tags.
|
||||
func RootNeedsUniqueTagsMigration(root *RootValue) (bool, error) {
|
||||
// SuperSchemas were added in the same update that required unique tags. If a root does not have a
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
// Copyright 2019 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package doltdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
func TestDocDiff(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ddb, _ := LoadDoltDB(ctx, types.Format_7_18, InMemDoltDB)
|
||||
ddb.WriteEmptyRepo(ctx, "billy bob", "bigbillieb@fake.horse")
|
||||
|
||||
cs, _ := NewCommitSpec("master")
|
||||
cm, _ := ddb.Resolve(ctx, cs, nil)
|
||||
|
||||
root, err := cm.GetRootValue()
|
||||
assert.NoError(t, err)
|
||||
|
||||
docDetails := []DocDetails{
|
||||
{DocPk: LicensePk},
|
||||
{DocPk: ReadmePk},
|
||||
}
|
||||
|
||||
// DocDiff between a root and itself should return no added, modified or removed docs.
|
||||
added, modified, removed, err := root.DocDiff(ctx, root, docDetails)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(added)+len(modified)+len(removed) != 0 {
|
||||
t.Error("Bad doc diff when comparing two repos")
|
||||
}
|
||||
|
||||
// Create tbl1 with one license row
|
||||
sch := createTestDocsSchema()
|
||||
licRow := makeDocRow(t, sch, LicensePk, types.String("license row"))
|
||||
m, _ := createTestRows(t, ddb.ValueReadWriter(), sch, []row.Row{licRow})
|
||||
tbl1, err := createTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create root2 with tbl1 on it (one doc: license)
|
||||
root2, err := root.PutTable(ctx, DocTableName, tbl1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// DocDiff between root and root2 should return one added doc, LICENSE.md
|
||||
added, modified, removed, err = root.DocDiff(ctx, root2, docDetails)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(added) != 1 || added[0] != "LICENSE.md" || len(modified)+len(removed) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
|
||||
// Create tbl2 with one readme row
|
||||
readmeRow := makeDocRow(t, sch, ReadmePk, types.String("readme row"))
|
||||
m, _ = createTestRows(t, ddb.ValueReadWriter(), sch, []row.Row{readmeRow})
|
||||
tbl2, err := createTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create root3 with tbl2 on it (one doc: readme)
|
||||
root3, err := root.PutTable(ctx, DocTableName, tbl2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// DocDiff between root2 and root3 should return one removed doc (license) and one added doc (readme).
|
||||
added, modified, removed, err = root2.DocDiff(ctx, root3, docDetails)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(removed) != 1 || removed[0] != "LICENSE.md" || len(added) != 1 || added[0] != "README.md" || len(modified) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
|
||||
// Create tbl3 with 2 doc rows (readme, license)
|
||||
readmeRowUpdated := makeDocRow(t, sch, ReadmePk, types.String("a different readme"))
|
||||
m, _ = createTestRows(t, ddb.ValueReadWriter(), sch, []row.Row{readmeRowUpdated, licRow})
|
||||
tbl3, err := createTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create root4 with tbl3 on it (two docs: readme and license)
|
||||
root4, err := root3.PutTable(ctx, DocTableName, tbl3)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// DocDiff between root3 and root4 should return one added doc (license) and one modified doc (readme).
|
||||
added, modified, removed, err = root3.DocDiff(ctx, root4, nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(added) != 1 || added[0] != "LICENSE.md" || len(modified) != 1 || modified[0] != "README.md" || len(removed) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
|
||||
// DocDiff between root4 and root shows 2 remove docs (license, readme)
|
||||
added, modified, removed, err = root4.DocDiff(ctx, root, nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if len(removed) != 2 || len(modified) != 0 || len(added) != 0 {
|
||||
t.Error("Bad table diff after adding a single table")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddNewerTextAndValueFromTable(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ddb, _ := LoadDoltDB(ctx, types.Format_7_18, InMemDoltDB)
|
||||
ddb.WriteEmptyRepo(ctx, "billy bob", "bigbillieb@fake.horse")
|
||||
|
||||
// If no tbl/schema is provided, doc NewerText and Value should be nil.
|
||||
doc1 := DocDetails{DocPk: LicensePk}
|
||||
doc1, err := AddNewerTextToDocFromTbl(ctx, nil, nil, doc1)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, doc1.NewerText)
|
||||
doc1, err = AddValueToDocFromTbl(ctx, nil, nil, doc1)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, doc1.Value)
|
||||
|
||||
// Create table with no rows
|
||||
sch := createTestDocsSchema()
|
||||
rows := []row.Row{}
|
||||
m, _ := createTestRows(t, ddb.ValueReadWriter(), sch, rows)
|
||||
tbl, err := createTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// If a table doesn't have doc row, doc NewerText and Value should remain nil
|
||||
doc2 := DocDetails{DocPk: LicensePk}
|
||||
doc2, err = AddNewerTextToDocFromTbl(ctx, tbl, &sch, doc2)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, doc2.NewerText)
|
||||
doc2, err = AddValueToDocFromTbl(ctx, tbl, &sch, doc2)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, doc2.Value)
|
||||
|
||||
// If a table doesn't have doc row, and NewerText and Value are originally non-nil, they should be updated to nil.
|
||||
doc3 := DocDetails{DocPk: LicensePk, NewerText: []byte("Something in newer text field"), Value: types.String("something")}
|
||||
doc3, err = AddNewerTextToDocFromTbl(ctx, tbl, &sch, doc3)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, doc3.NewerText)
|
||||
doc3, err = AddValueToDocFromTbl(ctx, tbl, &sch, doc3)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, doc3.Value)
|
||||
|
||||
// Update tbl to have 2 doc rows, readme and license
|
||||
rows = getDocRows(t, sch, types.String("text in doc_text"))
|
||||
m, _ = createTestRows(t, ddb.ValueReadWriter(), sch, rows)
|
||||
tbl, err = createTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// If a table has a doc row, NewerText and Value and should be updated to the `doc_text` value in that row.
|
||||
doc4 := DocDetails{DocPk: LicensePk, NewerText: []byte("Something in newer text field")}
|
||||
doc4, err = AddNewerTextToDocFromTbl(ctx, tbl, &sch, doc4)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "text in doc_text", string(doc4.NewerText))
|
||||
doc4, err = AddValueToDocFromTbl(ctx, tbl, &sch, doc4)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, types.String("text in doc_text"), doc4.Value)
|
||||
|
||||
// If a table has a doc row, and NewerText and Value are originally non-nil, they should be updated to the `doc_text` value.
|
||||
doc5 := DocDetails{DocPk: LicensePk}
|
||||
doc5, err = AddNewerTextToDocFromTbl(ctx, tbl, &sch, doc5)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "text in doc_text", string(doc5.NewerText))
|
||||
doc5, err = AddValueToDocFromTbl(ctx, tbl, &sch, doc5)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, types.String("text in doc_text"), doc5.Value)
|
||||
}
|
||||
|
||||
func TestAddNewerTextAndDocPkFromRow(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ddb, _ := LoadDoltDB(ctx, types.Format_7_18, InMemDoltDB)
|
||||
ddb.WriteEmptyRepo(ctx, "billy bob", "bigbillieb@fake.horse")
|
||||
|
||||
sch := createTestDocsSchema()
|
||||
|
||||
emptyRow, err := row.New(types.Format_7_18, sch, row.TaggedValues{})
|
||||
|
||||
// NewerText and DocPk should be nil from an empty row
|
||||
doc1 := DocDetails{}
|
||||
doc1, err = addNewerTextToDocFromRow(ctx, emptyRow, &doc1)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, doc1.NewerText)
|
||||
doc1, err = addDocPKToDocFromRow(emptyRow, &doc1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", doc1.DocPk)
|
||||
|
||||
licenseRow, err := row.New(types.Format_7_18, sch, row.TaggedValues{
|
||||
schema.DocNameTag: types.String(LicensePk),
|
||||
schema.DocTextTag: types.String("license!"),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// NewerText and DocPk should be added to doc from row
|
||||
doc2 := DocDetails{}
|
||||
doc2, err = addNewerTextToDocFromRow(ctx, licenseRow, &doc2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "license!", string(doc2.NewerText))
|
||||
doc1, err = addDocPKToDocFromRow(licenseRow, &doc2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, LicensePk, doc2.DocPk)
|
||||
|
||||
// When NewerText and DocPk are non-nil, they should be updated from the row provided.
|
||||
doc3 := DocDetails{DocPk: "invalid", NewerText: []byte("something")}
|
||||
doc3, err = addNewerTextToDocFromRow(ctx, licenseRow, &doc3)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "license!", string(doc3.NewerText))
|
||||
doc3, err = addDocPKToDocFromRow(licenseRow, &doc3)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, LicensePk, doc3.DocPk)
|
||||
}
|
||||
|
||||
func createTestDocsSchema() schema.Schema {
|
||||
typedColColl, _ := schema.NewColCollection(
|
||||
schema.NewColumn(DocPkColumnName, schema.DocNameTag, types.StringKind, true, schema.NotNullConstraint{}),
|
||||
schema.NewColumn(DocTextColumnName, schema.DocTextTag, types.StringKind, false),
|
||||
)
|
||||
sch, err := schema.SchemaFromCols(typedColColl)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return sch
|
||||
}
|
||||
|
||||
func getDocRows(t *testing.T, sch schema.Schema, rowVal types.Value) []row.Row {
|
||||
rows := make([]row.Row, 2)
|
||||
row1 := makeDocRow(t, sch, LicensePk, rowVal)
|
||||
rows[0] = row1
|
||||
row2 := makeDocRow(t, sch, ReadmePk, rowVal)
|
||||
rows[1] = row2
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func makeDocRow(t *testing.T, sch schema.Schema, pk string, rowVal types.Value) row.Row {
|
||||
row, err := row.New(types.Format_7_18, sch, row.TaggedValues{
|
||||
schema.DocNameTag: types.String(pk),
|
||||
schema.DocTextTag: rowVal,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
return row
|
||||
}
|
||||
|
||||
func createTestRows(t *testing.T, vrw types.ValueReadWriter, sch schema.Schema, rows []row.Row) (types.Map, []row.Row) {
|
||||
ctx := context.Background()
|
||||
var err error
|
||||
|
||||
m, err := types.NewMap(ctx, vrw)
|
||||
assert.NoError(t, err)
|
||||
ed := m.Edit()
|
||||
|
||||
for _, r := range rows {
|
||||
ed = ed.Set(r.NomsMapKey(sch), r.NomsMapValue(sch))
|
||||
}
|
||||
|
||||
m, err = ed.Map(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return m, rows
|
||||
}
|
||||
@@ -147,10 +147,6 @@ var generatedSystemTablePrefixes = []string{
|
||||
const (
|
||||
// DocTableName is the name of the dolt table containing documents such as the license and readme
|
||||
DocTableName = "dolt_docs"
|
||||
// LicensePk is the key for accessing the license within the docs table
|
||||
LicensePk = "LICENSE.md"
|
||||
// ReadmePk is the key for accessing the readme within the docs table
|
||||
ReadmePk = "README.md"
|
||||
// DocPkColumnName is the name of the pk column in the docs table
|
||||
DocPkColumnName = "doc_name"
|
||||
//DocTextColumnName is the name of the column containing the document contents in the docs table
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package doltdocs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/filesys"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
var ErrDocsUpdate = errors.New("error updating local docs")
|
||||
var ErrEmptyDocsTable = errors.New("error: All docs removed. Removing Docs Table")
|
||||
var ErrMarshallingSchema = errors.New("error marshalling schema")
|
||||
|
||||
var doltDocsColumns, _ = schema.NewColCollection(
|
||||
schema.NewColumn(doltdb.DocPkColumnName, schema.DocNameTag, types.StringKind, true, schema.NotNullConstraint{}),
|
||||
schema.NewColumn(doltdb.DocTextColumnName, schema.DocTextTag, types.StringKind, false),
|
||||
)
|
||||
var DoltDocsSchema = schema.MustSchemaFromCols(doltDocsColumns)
|
||||
|
||||
type Doc struct {
|
||||
Text []byte
|
||||
DocPk string
|
||||
File string
|
||||
}
|
||||
|
||||
type Docs []Doc
|
||||
|
||||
const (
|
||||
ReadmeFile = "../README.md"
|
||||
LicenseFile = "../LICENSE.md"
|
||||
|
||||
// LicenseDoc is the key for accessing the license within the docs table
|
||||
LicenseDoc = "LICENSE.md"
|
||||
// ReadmeDoc is the key for accessing the readme within the docs table
|
||||
ReadmeDoc = "README.md"
|
||||
)
|
||||
|
||||
var SupportedDocs = Docs{
|
||||
{DocPk: ReadmeDoc, File: ReadmeFile},
|
||||
{DocPk: LicenseDoc, File: LicenseFile},
|
||||
}
|
||||
|
||||
// GetLocalFileText returns a byte slice representing the contents of the provided file, if it exists
|
||||
func GetLocalFileText(fs filesys.Filesys, file string) ([]byte, error) {
|
||||
path := ""
|
||||
if DocFileExists(fs, file) {
|
||||
path = GetDocFilePath(file)
|
||||
}
|
||||
|
||||
if path != "" {
|
||||
return fs.ReadFile(path)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetSupportedDocs takes in a filesystem and returns the contents of all docs on disk.
|
||||
func GetSupportedDocs(fs filesys.Filesys) (docs Docs, err error) {
|
||||
docs = Docs{}
|
||||
for _, doc := range SupportedDocs {
|
||||
newerText, err := GetLocalFileText(fs, doc.File)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
doc.Text = newerText
|
||||
docs = append(docs, doc)
|
||||
}
|
||||
return docs, nil
|
||||
}
|
||||
|
||||
// GetDoc takes in a filesystem and a docName and returns the doc's contents.
|
||||
func GetDoc(fs filesys.Filesys, docName string) (doc Doc, err error) {
|
||||
for _, doc := range SupportedDocs {
|
||||
if doc.DocPk == docName {
|
||||
newerText, err := GetLocalFileText(fs, doc.File)
|
||||
if err != nil {
|
||||
return Doc{}, err
|
||||
}
|
||||
doc.Text = newerText
|
||||
return doc, nil
|
||||
}
|
||||
}
|
||||
return Doc{}, err
|
||||
}
|
||||
|
||||
func GetDocNamesFromDocs(docs Docs) []string {
|
||||
if docs == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret := make([]string, len(docs))
|
||||
|
||||
for i, doc := range docs {
|
||||
ret[i] = doc.DocPk
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetDocsFromRoot takes in a root value and returns the docs stored in its dolt_docs table.
|
||||
func GetDocsFromRoot(ctx context.Context, root *doltdb.RootValue, docNames ...string) (Docs, error) {
|
||||
docTbl, docTblFound, err := root.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sch schema.Schema
|
||||
if docTblFound {
|
||||
docSch, err := docTbl.GetSchema(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sch = docSch
|
||||
}
|
||||
|
||||
if docNames == nil {
|
||||
docNames = GetDocNamesFromDocs(SupportedDocs)
|
||||
}
|
||||
|
||||
docs := make(Docs, len(docNames))
|
||||
for i, name := range docNames {
|
||||
doc, isSupported := IsSupportedDoc(name)
|
||||
if !isSupported {
|
||||
return nil, fmt.Errorf("%s is not a supported doc", name)
|
||||
}
|
||||
|
||||
docText, err := getDocTextFromTbl(ctx, docTbl, &sch, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
doc.Text = docText
|
||||
docs[i] = doc
|
||||
}
|
||||
|
||||
return docs, nil
|
||||
}
|
||||
|
||||
// Save takes in a fs object and saves all the docs to the filesystem, overwriting any existing files.
|
||||
func (docs Docs) Save(fs filesys.ReadWriteFS) error {
|
||||
for _, doc := range docs {
|
||||
if _, ok := IsSupportedDoc(doc.DocPk); !ok {
|
||||
continue
|
||||
}
|
||||
filePath := GetDocFilePath(doc.File)
|
||||
if doc.Text != nil {
|
||||
err := fs.WriteFile(filePath, doc.Text)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := DeleteDoc(fs, doc.DocPk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDocFilePath takes in a filename and appends it to the DoltDir filepath.
|
||||
func GetDocFilePath(filename string) string {
|
||||
return filepath.Join(dbfactory.DoltDir, filename)
|
||||
}
|
||||
|
||||
// LoadDocs takes in a fs object and reads all the docs (ex. README.md) defined in SupportedDocs.
|
||||
func LoadDocs(fs filesys.ReadWriteFS) (Docs, error) {
|
||||
docsWithCurrentText := SupportedDocs
|
||||
for i, val := range docsWithCurrentText {
|
||||
path := GetDocFilePath(val.File)
|
||||
exists, isDir := fs.Exists(path)
|
||||
if exists && !isDir {
|
||||
data, err := fs.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
val.Text = data
|
||||
docsWithCurrentText[i] = val
|
||||
}
|
||||
}
|
||||
return docsWithCurrentText, nil
|
||||
}
|
||||
|
||||
func IsSupportedDoc(docName string) (Doc, bool) {
|
||||
for _, doc := range SupportedDocs {
|
||||
if doc.DocPk == docName {
|
||||
return doc, true
|
||||
}
|
||||
}
|
||||
return Doc{}, false
|
||||
}
|
||||
|
||||
func DocFileExists(fs filesys.ReadWriteFS, file string) bool {
|
||||
exists, isDir := fs.Exists(GetDocFilePath(file))
|
||||
return exists && !isDir
|
||||
}
|
||||
|
||||
// DeleteDoc takes in a filesytem object and deletes the file with docName, if it's a SupportedDoc.
|
||||
func DeleteDoc(fs filesys.ReadWriteFS, docName string) error {
|
||||
if doc, ok := IsSupportedDoc(docName); ok {
|
||||
if doc.DocPk == docName {
|
||||
path := GetDocFilePath(doc.File)
|
||||
exists, isDir := fs.Exists(path)
|
||||
if exists && !isDir {
|
||||
return fs.DeleteFile(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateRootWithDocs takes in a root value, and some docs and writes those docs to the dolt_docs table
|
||||
// (perhaps creating it in the process). The table might not necessarily need to be created if there are no docs in the
|
||||
// repo yet.
|
||||
func UpdateRootWithDocs(ctx context.Context, root *doltdb.RootValue, docs Docs) (*doltdb.RootValue, error) {
|
||||
docTbl, err := CreateOrUpdateDocsTable(ctx, root, docs)
|
||||
|
||||
if errors.Is(ErrEmptyDocsTable, err) {
|
||||
root, err = root.RemoveTables(ctx, doltdb.DocTableName)
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// There might not need be a need to create docs table if not docs have been created yet so check if docTbl != nil.
|
||||
if docTbl != nil {
|
||||
root, err = root.PutTable(ctx, doltdb.DocTableName, docTbl)
|
||||
}
|
||||
|
||||
return root, nil
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package doltdocs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema/encoding"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/table"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/table/typed/noms"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
// updateDocsTable takes in docTbl param and updates it with the value in docs. It returns the updated table.
|
||||
func updateDocsTable(ctx context.Context, docTbl *doltdb.Table, docs Docs) (*doltdb.Table, error) {
|
||||
m, err := docTbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sch, err := docTbl.GetSchema(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
me := m.Edit()
|
||||
for _, doc := range docs {
|
||||
key, err := docTblKeyFromName(docTbl.Format(), doc.DocPk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
docRow, exists, err := table.GetRow(ctx, docTbl, sch, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if exists && doc.Text == nil {
|
||||
me = me.Remove(docRow.NomsMapKey(sch))
|
||||
} else if doc.Text != nil {
|
||||
docTaggedVals := row.TaggedValues{
|
||||
schema.DocNameTag: types.String(doc.DocPk),
|
||||
schema.DocTextTag: types.String(doc.Text),
|
||||
}
|
||||
docRow, err = row.New(types.Format_7_18, sch, docTaggedVals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
me = me.Set(docRow.NomsMapKey(sch), docRow.NomsMapValue(sch))
|
||||
}
|
||||
}
|
||||
updatedMap, err := me.Map(ctx)
|
||||
if updatedMap.Len() == 0 {
|
||||
return nil, ErrEmptyDocsTable
|
||||
}
|
||||
|
||||
docTbl, err = docTbl.UpdateRows(ctx, updatedMap)
|
||||
|
||||
return docTbl, err
|
||||
}
|
||||
|
||||
// createDocsTable creates a new in memory table that stores the given doc details.
|
||||
func createDocsTable(ctx context.Context, vrw types.ValueReadWriter, docs Docs) (*doltdb.Table, error) {
|
||||
imt := table.NewInMemTable(DoltDocsSchema)
|
||||
|
||||
// Determines if the table needs to be created at all and initializes a schema if it does.
|
||||
createTable := false
|
||||
for _, doc := range docs {
|
||||
if doc.Text != nil {
|
||||
createTable = true
|
||||
docTaggedVals := row.TaggedValues{
|
||||
schema.DocNameTag: types.String(doc.DocPk),
|
||||
schema.DocTextTag: types.String(doc.Text),
|
||||
}
|
||||
|
||||
docRow, err := row.New(types.Format_7_18, DoltDocsSchema, docTaggedVals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = imt.AppendRow(docRow)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if createTable {
|
||||
rd := table.NewInMemTableReader(imt)
|
||||
wr := noms.NewNomsMapCreator(context.Background(), vrw, DoltDocsSchema)
|
||||
|
||||
_, _, err := table.PipeRows(context.Background(), rd, wr, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rd.Close(context.Background())
|
||||
wr.Close(context.Background())
|
||||
|
||||
schVal, err := encoding.MarshalSchemaAsNomsValue(ctx, vrw, wr.GetSchema())
|
||||
|
||||
if err != nil {
|
||||
return nil, ErrMarshallingSchema
|
||||
}
|
||||
|
||||
empty, err := types.NewMap(ctx, vrw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newDocsTbl, err := doltdb.NewTable(ctx, vrw, schVal, wr.GetMap(), empty)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newDocsTbl, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// CreateOrUpdateDocsTable takes a root value and a set of docs and either creates the docs table or updates it with docs.
|
||||
func CreateOrUpdateDocsTable(ctx context.Context, root *doltdb.RootValue, docs Docs) (*doltdb.Table, error) {
|
||||
docsTbl, found, err := root.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if found {
|
||||
return updateDocsTable(ctx, docsTbl, docs)
|
||||
} else {
|
||||
return createDocsTable(ctx, root.VRW(), docs)
|
||||
}
|
||||
}
|
||||
|
||||
func docTblKeyFromName(fmt *types.NomsBinFormat, name string) (types.Tuple, error) {
|
||||
return types.NewTuple(fmt, types.Uint(schema.DocNameTag), types.String(name))
|
||||
}
|
||||
|
||||
// getDocTextFromTbl returns the Text field of a doc using the provided table and schema and primary key.
|
||||
func getDocTextFromTbl(ctx context.Context, tbl *doltdb.Table, sch *schema.Schema, docPk string) ([]byte, error) {
|
||||
if tbl != nil && sch != nil {
|
||||
key, err := docTblKeyFromName(tbl.Format(), docPk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
docRow, ok, err := getDocRow(ctx, tbl, *sch, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
docValue, _ := docRow.GetColVal(schema.DocTextTag)
|
||||
return []byte(docValue.(types.String)), nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// getDocRow returns the associated row of a particular doc from the docTbl given.
|
||||
func getDocRow(ctx context.Context, docTbl *doltdb.Table, sch schema.Schema, key types.Tuple) (r row.Row, ok bool, err error) {
|
||||
rowMap, err := docTbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
var fields types.Value
|
||||
fields, ok, err = rowMap.MaybeGet(ctx, key)
|
||||
if err != nil || !ok {
|
||||
return nil, ok, err
|
||||
}
|
||||
|
||||
r, err = row.FromNoms(sch, key, fields.(types.Tuple))
|
||||
return r, ok, err
|
||||
}
|
||||
|
||||
// getDocTextFromRow updates return the text field of a provided row.
|
||||
func getDocTextFromRow(r row.Row) ([]byte, error) {
|
||||
docValue, ok := r.GetColVal(schema.DocTextTag)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
} else {
|
||||
docValStr, err := strconv.Unquote(docValue.HumanReadableString())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(docValStr), nil
|
||||
}
|
||||
}
|
||||
|
||||
// getDocPKFromRow updates returns the docPk field of a given row.
|
||||
func getDocPKFromRow(r row.Row) (string, error) {
|
||||
colVal, _ := r.GetColVal(schema.DocNameTag)
|
||||
if colVal == nil {
|
||||
return "", nil
|
||||
} else {
|
||||
docName, err := strconv.Unquote(colVal.HumanReadableString())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return docName, nil
|
||||
}
|
||||
}
|
||||
|
||||
// getFileFromDoc returns the file obj associated with the doc
|
||||
func getFileFromDoc(docName string) (string, error) {
|
||||
if doc, ok := IsSupportedDoc(docName); ok {
|
||||
return doc.File, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Doc name not provided %s", docName)
|
||||
}
|
||||
|
||||
// GetAllDocs takes a root value and returns all the docs available in the root.
|
||||
func GetAllDocs(ctx context.Context, root *doltdb.RootValue) (Docs, bool, error) {
|
||||
if root == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
docsTbl, found, err := root.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if !found {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
docs, err := getDocsFromTable(ctx, docsTbl)
|
||||
return docs, true, err
|
||||
}
|
||||
|
||||
// getDocsFromTable takes the doltdocs table and a schema and return all docs in the dolt_docs table.
|
||||
func getDocsFromTable(ctx context.Context, table *doltdb.Table) (Docs, error) {
|
||||
ret := make(Docs, 0)
|
||||
|
||||
sch, err := table.GetSchema(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := table.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = rows.IterAll(ctx, func(key, val types.Value) error {
|
||||
newRow, err := row.FromNoms(sch, key.(types.Tuple), val.(types.Tuple))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cols := sch.GetAllCols().GetColumns()
|
||||
colVals := make([]types.Value, len(cols))
|
||||
for i, col := range cols {
|
||||
colval, ok := newRow.GetColVal(col.Tag)
|
||||
if !ok {
|
||||
return errors.New("error: could not get doc column value")
|
||||
}
|
||||
colVals[i] = colval
|
||||
}
|
||||
|
||||
if len(colVals) < 2 {
|
||||
return errors.New("error: not enough values read from the table")
|
||||
}
|
||||
|
||||
doc := Doc{}
|
||||
doc.DocPk = string(colVals[0].(types.String))
|
||||
doc.Text = []byte(colVals[1].(types.String))
|
||||
ret = append(ret, doc)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return ret, err
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package doltdocs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema/encoding"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
func TestAddNewerTextAndValueFromTable(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ddb, _ := doltdb.LoadDoltDB(ctx, types.Format_7_18, doltdb.InMemDoltDB)
|
||||
ddb.WriteEmptyRepo(ctx, "billy bob", "bigbillieb@fake.horse")
|
||||
|
||||
// If no tbl/schema is provided, doc Text and Value should be nil.
|
||||
doc1 := Doc{DocPk: LicenseDoc}
|
||||
doc1Text, err := getDocTextFromTbl(ctx, nil, nil, doc1.DocPk)
|
||||
assert.NoError(t, err)
|
||||
doc1.Text = doc1Text
|
||||
assert.Nil(t, doc1.Text)
|
||||
|
||||
// Create table with no rows
|
||||
sch := createTestDocsSchema()
|
||||
rows := []row.Row{}
|
||||
m, _ := createTestRows(t, ddb.ValueReadWriter(), sch, rows)
|
||||
tbl, err := CreateTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// If a table doesn't have doc row, doc Text and Value should remain nil
|
||||
doc2 := Doc{DocPk: LicenseDoc}
|
||||
doc2Text, err := getDocTextFromTbl(ctx, tbl, &sch, doc2.DocPk)
|
||||
assert.NoError(t, err)
|
||||
doc2.Text = doc2Text
|
||||
assert.Nil(t, doc2.Text)
|
||||
|
||||
// If a table doesn't have doc row, and Text and Value are originally non-nil, they should be updated to nil.
|
||||
doc3 := Doc{DocPk: LicenseDoc, Text: []byte("Something in newer text field")}
|
||||
doc3Text, err := getDocTextFromTbl(ctx, tbl, &sch, doc3.DocPk)
|
||||
assert.NoError(t, err)
|
||||
doc3.Text = doc3Text
|
||||
assert.Nil(t, doc3.Text)
|
||||
|
||||
// Update tbl to have 2 doc rows, readme and license
|
||||
rows = getDocRows(t, sch, types.String("text in doc_text"))
|
||||
m, _ = createTestRows(t, ddb.ValueReadWriter(), sch, rows)
|
||||
tbl, err = CreateTestTable(ddb.ValueReadWriter(), sch, m)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// If a table has a doc row, Text and Value and should be updated to the `doc_text` value in that row.
|
||||
doc4 := Doc{DocPk: LicenseDoc, Text: []byte("Something in newer text field")}
|
||||
doc4Text, err := getDocTextFromTbl(ctx, tbl, &sch, doc4.DocPk)
|
||||
assert.NoError(t, err)
|
||||
doc4.Text = doc4Text
|
||||
assert.Equal(t, "text in doc_text", string(doc4.Text))
|
||||
|
||||
// If a table has a doc row, and Text and Value are originally non-nil, they should be updated to the `doc_text` value.
|
||||
doc5 := Doc{DocPk: LicenseDoc}
|
||||
doc5Text, err := getDocTextFromTbl(ctx, tbl, &sch, doc5.DocPk)
|
||||
assert.NoError(t, err)
|
||||
doc5.Text = doc5Text
|
||||
assert.Equal(t, "text in doc_text", string(doc5.Text))
|
||||
}
|
||||
|
||||
func TestAddNewerTextAndDocPkFromRow(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ddb, _ := doltdb.LoadDoltDB(ctx, types.Format_7_18, doltdb.InMemDoltDB)
|
||||
ddb.WriteEmptyRepo(ctx, "billy bob", "bigbillieb@fake.horse")
|
||||
|
||||
sch := createTestDocsSchema()
|
||||
|
||||
emptyRow, err := row.New(types.Format_7_18, sch, row.TaggedValues{})
|
||||
|
||||
// Text and DocName should be nil from an empty row
|
||||
doc1 := Doc{}
|
||||
text, err := getDocTextFromRow(emptyRow)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, text)
|
||||
docPk, err := getDocPKFromRow(emptyRow)
|
||||
assert.NoError(t, err)
|
||||
doc1.DocPk = docPk
|
||||
assert.Equal(t, "", doc1.DocPk)
|
||||
|
||||
licenseRow, err := row.New(types.Format_7_18, sch, row.TaggedValues{
|
||||
schema.DocNameTag: types.String(LicenseDoc),
|
||||
schema.DocTextTag: types.String("license!"),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Text and DocName should be added to doc from row
|
||||
doc2 := Doc{}
|
||||
text, err = getDocTextFromRow(licenseRow)
|
||||
assert.NoError(t, err)
|
||||
doc2.Text = text
|
||||
assert.Equal(t, "license!", string(doc2.Text))
|
||||
docPk, err = getDocPKFromRow(licenseRow)
|
||||
assert.NoError(t, err)
|
||||
doc2.DocPk = docPk
|
||||
assert.Equal(t, LicenseDoc, doc2.DocPk)
|
||||
|
||||
// When Text and DocName are non-nil, they should be updated from the row provided.
|
||||
doc3 := Doc{DocPk: "invalid", Text: []byte("something")}
|
||||
text, err = getDocTextFromRow(licenseRow)
|
||||
assert.NoError(t, err)
|
||||
doc3.Text = text
|
||||
assert.Equal(t, "license!", string(doc3.Text))
|
||||
docPk, err = getDocPKFromRow(licenseRow)
|
||||
assert.NoError(t, err)
|
||||
doc3.DocPk = docPk
|
||||
assert.Equal(t, LicenseDoc, doc3.DocPk)
|
||||
}
|
||||
|
||||
func CreateTestTable(vrw types.ValueReadWriter, tSchema schema.Schema, rowData types.Map) (*doltdb.Table, error) {
|
||||
schemaVal, err := encoding.MarshalSchemaAsNomsValue(context.Background(), vrw, tSchema)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
empty, _ := types.NewMap(context.Background(), vrw)
|
||||
tbl, err := doltdb.NewTable(context.Background(), vrw, schemaVal, rowData, empty)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tbl, nil
|
||||
}
|
||||
|
||||
func createTestDocsSchema() schema.Schema {
|
||||
typedColColl, _ := schema.NewColCollection(
|
||||
schema.NewColumn(doltdb.DocPkColumnName, schema.DocNameTag, types.StringKind, true, schema.NotNullConstraint{}),
|
||||
schema.NewColumn(doltdb.DocTextColumnName, schema.DocTextTag, types.StringKind, false),
|
||||
)
|
||||
sch, err := schema.SchemaFromCols(typedColColl)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return sch
|
||||
}
|
||||
|
||||
func getDocRows(t *testing.T, sch schema.Schema, rowVal types.Value) []row.Row {
|
||||
rows := make([]row.Row, 2)
|
||||
row1 := makeDocRow(t, sch, LicenseDoc, rowVal)
|
||||
rows[0] = row1
|
||||
row2 := makeDocRow(t, sch, ReadmeDoc, rowVal)
|
||||
rows[1] = row2
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func makeDocRow(t *testing.T, sch schema.Schema, pk string, rowVal types.Value) row.Row {
|
||||
row, err := row.New(types.Format_7_18, sch, row.TaggedValues{
|
||||
schema.DocNameTag: types.String(pk),
|
||||
schema.DocTextTag: rowVal,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
return row
|
||||
}
|
||||
|
||||
func createTestRows(t *testing.T, vrw types.ValueReadWriter, sch schema.Schema, rows []row.Row) (types.Map, []row.Row) {
|
||||
ctx := context.Background()
|
||||
var err error
|
||||
|
||||
m, err := types.NewMap(ctx, vrw)
|
||||
assert.NoError(t, err)
|
||||
ed := m.Edit()
|
||||
|
||||
for _, r := range rows {
|
||||
ed = ed.Set(r.NomsMapKey(sch), r.NomsMapValue(sch))
|
||||
}
|
||||
|
||||
m, err = ed.Map(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
return m, rows
|
||||
}
|
||||
+1
-1
@@ -264,7 +264,7 @@ func CheckoutBranch(ctx context.Context, dEnv *env.DoltEnv, brName string) error
|
||||
return err
|
||||
}
|
||||
|
||||
unstagedDocs, err := GetUnstagedDocs(ctx, dEnv)
|
||||
unstagedDocs, err := GetUnstagedDocs(ctx, dEnv.DbData())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
// Copyright 2019 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package actions contains utility methods for inspecting and manipulating a dolt data repository's state.
|
||||
package actions
|
||||
+71
-32
@@ -16,6 +16,9 @@ package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/diff"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
@@ -30,7 +33,7 @@ func SaveTrackedDocsFromWorking(ctx context.Context, dEnv *env.DoltEnv) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return SaveTrackedDocs(ctx, dEnv, workingRoot, workingRoot, localDocs)
|
||||
return SaveTrackedDocs(ctx, dEnv.DocsReadWriter(), workingRoot, workingRoot, localDocs)
|
||||
}
|
||||
|
||||
// SaveDocsFromWorking saves docs from the working root to the filesystem, and could overwrite untracked docs.
|
||||
@@ -46,11 +49,17 @@ func SaveDocsFromWorking(ctx context.Context, dEnv *env.DoltEnv) error {
|
||||
// SaveDocsFromRoot saves docs from the root given to the filesystem, and could overwrite untracked docs.
|
||||
func SaveDocsFromRoot(ctx context.Context, root *doltdb.RootValue, dEnv *env.DoltEnv) error {
|
||||
localDocs := dEnv.Docs
|
||||
drw := dEnv.DocsReadWriter()
|
||||
|
||||
err := dEnv.UpdateFSDocsToRootDocs(ctx, root, nil)
|
||||
docs, err := doltdocs.GetDocsFromRoot(ctx, root, doltdocs.GetDocNamesFromDocs(doltdocs.SupportedDocs)...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = drw.WriteDocsToDisk(docs)
|
||||
if err != nil {
|
||||
// If we can't update docs on disk, attempt to revert the change
|
||||
localDocs.Save(dEnv.FS)
|
||||
drw.WriteDocsToDisk(localDocs)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -58,7 +67,7 @@ func SaveDocsFromRoot(ctx context.Context, root *doltdb.RootValue, dEnv *env.Dol
|
||||
}
|
||||
|
||||
// SaveTrackedDocs writes the docs from the targetRoot to the filesystem. The working root is used to identify untracked docs, which are left unchanged.
|
||||
func SaveTrackedDocs(ctx context.Context, dEnv *env.DoltEnv, workRoot, targetRoot *doltdb.RootValue, localDocs env.Docs) error {
|
||||
func SaveTrackedDocs(ctx context.Context, drw env.DocsReadWriter, workRoot, targetRoot *doltdb.RootValue, localDocs doltdocs.Docs) error {
|
||||
docDiffs, err := diff.NewDocDiffs(ctx, workRoot, nil, localDocs)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -66,21 +75,22 @@ func SaveTrackedDocs(ctx context.Context, dEnv *env.DoltEnv, workRoot, targetRoo
|
||||
|
||||
docs := removeUntrackedDocs(localDocs, docDiffs)
|
||||
|
||||
err = dEnv.UpdateFSDocsToRootDocs(ctx, targetRoot, docs)
|
||||
docs, err = doltdocs.GetDocsFromRoot(ctx, targetRoot, doltdocs.GetDocNamesFromDocs(docs)...)
|
||||
if err != nil {
|
||||
localDocs.Save(dEnv.FS)
|
||||
return err
|
||||
}
|
||||
|
||||
err = drw.WriteDocsToDisk(docs)
|
||||
|
||||
if err != nil {
|
||||
// If we can't update docs on disk, attempt to revert the change
|
||||
_ = drw.WriteDocsToDisk(localDocs)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveDocsFromDocDetails saves the provided docs to the filesystem.
|
||||
// An untracked doc will be overwritten if doc.NewerText == nil.
|
||||
func SaveDocsFromDocDetails(dEnv *env.DoltEnv, docs env.Docs) error {
|
||||
return docs.Save(dEnv.FS)
|
||||
}
|
||||
|
||||
func docIsUntracked(doc string, untracked []string) bool {
|
||||
for _, val := range untracked {
|
||||
if doc == val {
|
||||
@@ -90,8 +100,8 @@ func docIsUntracked(doc string, untracked []string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func removeUntrackedDocs(docs []doltdb.DocDetails, docDiffs *diff.DocDiffs) []doltdb.DocDetails {
|
||||
result := []doltdb.DocDetails{}
|
||||
func removeUntrackedDocs(docs doltdocs.Docs, docDiffs *diff.DocDiffs) doltdocs.Docs {
|
||||
result := doltdocs.Docs{}
|
||||
untracked := getUntrackedDocs(docs, docDiffs)
|
||||
|
||||
for _, doc := range docs {
|
||||
@@ -102,7 +112,7 @@ func removeUntrackedDocs(docs []doltdb.DocDetails, docDiffs *diff.DocDiffs) []do
|
||||
return result
|
||||
}
|
||||
|
||||
func getUntrackedDocs(docs []doltdb.DocDetails, docDiffs *diff.DocDiffs) []string {
|
||||
func getUntrackedDocs(docs doltdocs.Docs, docDiffs *diff.DocDiffs) []string {
|
||||
untracked := []string{}
|
||||
for _, docName := range docDiffs.Docs {
|
||||
dt := docDiffs.DocToType[docName]
|
||||
@@ -114,59 +124,63 @@ func getUntrackedDocs(docs []doltdb.DocDetails, docDiffs *diff.DocDiffs) []strin
|
||||
return untracked
|
||||
}
|
||||
|
||||
func getUpdatedWorkingAndStagedWithDocs(ctx context.Context, dEnv *env.DoltEnv, working, staged, head *doltdb.RootValue, docDetails []doltdb.DocDetails) (currRoot, stgRoot *doltdb.RootValue, err error) {
|
||||
func getUpdatedWorkingAndStagedWithDocs(ctx context.Context, working, staged, head *doltdb.RootValue, docs doltdocs.Docs) (currRoot, stgRoot *doltdb.RootValue, retDocs doltdocs.Docs, err error) {
|
||||
root := head
|
||||
_, ok, err := staged.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
} else if ok {
|
||||
root = staged
|
||||
}
|
||||
|
||||
docs, err := dEnv.GetDocsWithNewerTextFromRoot(ctx, root, docDetails)
|
||||
docs, err = doltdocs.GetDocsFromRoot(ctx, root, doltdocs.GetDocNamesFromDocs(docs)...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
currRoot, err = dEnv.GetUpdatedRootWithDocs(ctx, working, docs)
|
||||
currRoot, err = doltdocs.UpdateRootWithDocs(ctx, working, docs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
stgRoot, err = dEnv.GetUpdatedRootWithDocs(ctx, staged, docs)
|
||||
stgRoot, err = doltdocs.UpdateRootWithDocs(ctx, staged, docs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return currRoot, stgRoot, nil
|
||||
return currRoot, stgRoot, docs, nil
|
||||
}
|
||||
|
||||
// GetUnstagedDocs retrieves the unstaged docs (docs from the filesystem).
|
||||
func GetUnstagedDocs(ctx context.Context, dEnv *env.DoltEnv) (env.Docs, error) {
|
||||
_, unstagedDocDiffs, err := diff.GetDocDiffs(ctx, dEnv.DoltDB, dEnv.RepoStateReader(), dEnv.DocsReadWriter())
|
||||
func GetUnstagedDocs(ctx context.Context, dbData env.DbData) (doltdocs.Docs, error) {
|
||||
_, unstagedDocDiffs, err := diff.GetDocDiffs(ctx, dbData.Ddb, dbData.Rsr, dbData.Drw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
unstagedDocs := env.Docs{}
|
||||
unstagedDocs := doltdocs.Docs{}
|
||||
for _, docName := range unstagedDocDiffs.Docs {
|
||||
docDetail, err := dEnv.GetDocDetail(docName)
|
||||
docAr, err := dbData.Drw.GetDocsOnDisk(docName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
unstagedDocs = append(unstagedDocs, docDetail)
|
||||
if len(docAr) < 1 {
|
||||
return nil, errors.New("error: Failed getting unstaged docs")
|
||||
}
|
||||
|
||||
unstagedDocs = append(unstagedDocs, docAr[0])
|
||||
}
|
||||
return unstagedDocs, nil
|
||||
}
|
||||
|
||||
// SaveDocsFromWorkingExcludingFSChanges saves docs from the working root to the filesystem, and does not overwrite changes to docs on the FS.
|
||||
// Intended to be called after checking that no conflicts exist (during a checkout or merge, i.e.).
|
||||
func SaveDocsFromWorkingExcludingFSChanges(ctx context.Context, dEnv *env.DoltEnv, docsToExclude env.Docs) error {
|
||||
func SaveDocsFromWorkingExcludingFSChanges(ctx context.Context, dEnv *env.DoltEnv, docsToExclude doltdocs.Docs) error {
|
||||
workingRoot, err := dEnv.WorkingRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var docsToSave env.Docs
|
||||
var docsToSave doltdocs.Docs
|
||||
if len(docsToExclude) > 0 {
|
||||
for _, doc := range dEnv.Docs {
|
||||
for _, excludedDoc := range docsToExclude {
|
||||
@@ -179,5 +193,30 @@ func SaveDocsFromWorkingExcludingFSChanges(ctx context.Context, dEnv *env.DoltEn
|
||||
docsToSave = dEnv.Docs
|
||||
}
|
||||
|
||||
return SaveTrackedDocs(ctx, dEnv, workingRoot, workingRoot, docsToSave)
|
||||
return SaveTrackedDocs(ctx, dEnv.DocsReadWriter(), workingRoot, workingRoot, docsToSave)
|
||||
}
|
||||
|
||||
// GetTablesOrDocs takes a slice of table or file names. Table names are returned as given. Supported doc names are
|
||||
// read from disk and their name replace with the names of the dolt_docs system table in the input slice. Supported docs
|
||||
// are returned in the second return param.
|
||||
func GetTablesOrDocs(drw env.DocsReadWriter, tablesOrFiles []string) (tables []string, docs doltdocs.Docs, err error) {
|
||||
for i, tbl := range tablesOrFiles {
|
||||
if _, ok := doltdocs.IsSupportedDoc(tbl); ok {
|
||||
docAr, err := drw.GetDocsOnDisk(tbl)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(docAr) < 1 {
|
||||
return nil, nil, errors.New("error: Failed getting docs")
|
||||
}
|
||||
|
||||
doc := docAr[0]
|
||||
if doc.DocPk == "" {
|
||||
return nil, nil, errors.New("Supported doc not found on disk.")
|
||||
}
|
||||
docs = append(docs, doc)
|
||||
tablesOrFiles[i] = doltdb.DocTableName
|
||||
}
|
||||
}
|
||||
return tablesOrFiles, docs, nil
|
||||
}
|
||||
|
||||
+16
-8
@@ -19,6 +19,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
@@ -169,15 +170,14 @@ func ResetSoftTables(ctx context.Context, dbData env.DbData, apr *argparser.ArgP
|
||||
return stagedRoot, nil
|
||||
}
|
||||
|
||||
func ResetSoft(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgParseResults, stagedRoot, headRoot *doltdb.RootValue) (*doltdb.RootValue, error) {
|
||||
func ResetSoft(ctx context.Context, dbData env.DbData, apr *argparser.ArgParseResults, stagedRoot, headRoot *doltdb.RootValue) (*doltdb.RootValue, error) {
|
||||
tables, err := getUnionedTables(ctx, apr.Args(), stagedRoot, headRoot)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbData := dEnv.DbData()
|
||||
tables, docs, err := GetTblsAndDocDetails(dbData.Drw, tables)
|
||||
tables, docs, err := GetTablesOrDocs(dbData.Drw, tables)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -192,7 +192,7 @@ func ResetSoft(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgParseRe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stagedRoot, err = resetDocs(ctx, dEnv, headRoot, docs)
|
||||
stagedRoot, err = resetDocs(ctx, dbData, headRoot, stagedRoot, docs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -219,18 +219,26 @@ func getUnionedTables(ctx context.Context, tables []string, stagedRoot, headRoot
|
||||
return tables, nil
|
||||
}
|
||||
|
||||
func resetDocs(ctx context.Context, dEnv *env.DoltEnv, headRoot *doltdb.RootValue, docDetails env.Docs) (newStgRoot *doltdb.RootValue, err error) {
|
||||
docs, err := dEnv.GetDocsWithNewerTextFromRoot(ctx, headRoot, docDetails)
|
||||
// resetDocs resets the working and staged docs with docs from head.
|
||||
func resetDocs(ctx context.Context, dbData env.DbData, headRoot *doltdb.RootValue, staged *doltdb.RootValue, docs doltdocs.Docs) (newStgRoot *doltdb.RootValue, err error) {
|
||||
docs, err = doltdocs.GetDocsFromRoot(ctx, headRoot, doltdocs.GetDocNamesFromDocs(docs)...)
|
||||
|
||||
working, err := env.WorkingRoot(ctx, dbData.Ddb, dbData.Rsr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = dEnv.PutDocsToWorking(ctx, docs)
|
||||
working, err = doltdocs.UpdateRootWithDocs(ctx, working, docs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dEnv.PutDocsToStaged(ctx, docs)
|
||||
_, err = env.UpdateWorkingRoot(ctx, dbData.Ddb, dbData.Rsw, working)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return doltdocs.UpdateRootWithDocs(ctx, staged, docs)
|
||||
}
|
||||
|
||||
func resetStaged(ctx context.Context, ddb *doltdb.DoltDB, rsw env.RepoStateWriter, tbls []string, staged, head *doltdb.RootValue) (*doltdb.RootValue, error) {
|
||||
|
||||
+24
-33
@@ -18,6 +18,8 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
)
|
||||
@@ -30,60 +32,37 @@ func StageTables(ctx context.Context, dbData env.DbData, tbls []string) error {
|
||||
rsw := dbData.Rsw
|
||||
drw := dbData.Drw
|
||||
|
||||
tables, docDetails, err := GetTblsAndDocDetails(drw, tbls)
|
||||
tables, docs, err := GetTablesOrDocs(drw, tbls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(docDetails) > 0 {
|
||||
err = drw.PutDocsToWorking(ctx, docDetails)
|
||||
staged, working, err := getStagedAndWorking(ctx, ddb, rsr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(docs) > 0 {
|
||||
working, err = doltdocs.UpdateRootWithDocs(ctx, working, docs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
staged, working, err := getStagedAndWorking(ctx, ddb, rsr)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = stageTables(ctx, ddb, rsw, tables, staged, working)
|
||||
if err != nil {
|
||||
drw.ResetWorkingDocsToStagedDocs(ctx)
|
||||
env.ResetWorkingDocsToStagedDocs(ctx, ddb, rsr, rsw)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTblsAndDocDetails takes a slice of strings where valid doc names are replaced with doc table name. Doc names are
|
||||
// appended to a docDetails slice. We return a tuple of tables, docDetails and error.
|
||||
func GetTblsAndDocDetails(drw env.DocsReadWriter, tbls []string) (tables []string, docDetails []doltdb.DocDetails, err error) {
|
||||
for i, tbl := range tbls {
|
||||
docDetail, err := drw.GetDocDetail(tbl)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if docDetail.DocPk != "" {
|
||||
docDetails = append(docDetails, docDetail)
|
||||
tbls[i] = doltdb.DocTableName
|
||||
}
|
||||
}
|
||||
return tbls, docDetails, nil
|
||||
}
|
||||
|
||||
func StageAllTables(ctx context.Context, dbData env.DbData) error {
|
||||
ddb := dbData.Ddb
|
||||
rsr := dbData.Rsr
|
||||
rsw := dbData.Rsw
|
||||
drw := dbData.Drw
|
||||
|
||||
err := drw.PutDocsToWorking(ctx, nil)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
staged, err := env.StagedRoot(ctx, ddb, rsr)
|
||||
|
||||
if err != nil {
|
||||
@@ -96,6 +75,18 @@ func StageAllTables(ctx context.Context, dbData env.DbData) error {
|
||||
return err
|
||||
}
|
||||
|
||||
docs, err := drw.GetDocsOnDisk()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
working, err = doltdocs.UpdateRootWithDocs(ctx, working, docs)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tbls, err := doltdb.UnionTableNames(ctx, staged, working)
|
||||
|
||||
if err != nil {
|
||||
@@ -104,7 +95,7 @@ func StageAllTables(ctx context.Context, dbData env.DbData) error {
|
||||
|
||||
err = stageTables(ctx, ddb, rsw, tbls, staged, working)
|
||||
if err != nil {
|
||||
drw.ResetWorkingDocsToStagedDocs(ctx)
|
||||
env.ResetWorkingDocsToStagedDocs(ctx, ddb, rsr, rsw)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
+7
-5
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/diff"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/set"
|
||||
)
|
||||
@@ -36,13 +37,13 @@ func CheckoutAllTables(ctx context.Context, dEnv *env.DoltEnv) error {
|
||||
return err
|
||||
}
|
||||
|
||||
docs := *env.AllValidDocDetails
|
||||
docs := doltdocs.SupportedDocs
|
||||
|
||||
return checkoutTablesAndDocs(ctx, dEnv, roots, tbls, docs)
|
||||
|
||||
}
|
||||
|
||||
func CheckoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, tbls []string, docs []doltdb.DocDetails) error {
|
||||
func CheckoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, tbls []string, docs doltdocs.Docs) error {
|
||||
roots, err := getRoots(ctx, dEnv.DoltDB, dEnv.RepoStateReader(), WorkingRoot, StagedRoot, HeadRoot)
|
||||
|
||||
if err != nil {
|
||||
@@ -127,7 +128,7 @@ func MoveTablesBetweenRoots(ctx context.Context, tbls []string, src, dest *doltd
|
||||
return dest, nil
|
||||
}
|
||||
|
||||
func checkoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, roots map[RootType]*doltdb.RootValue, tbls []string, docs []doltdb.DocDetails) error {
|
||||
func checkoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, roots map[RootType]*doltdb.RootValue, tbls []string, docs doltdocs.Docs) error {
|
||||
unknownTbls := []string{}
|
||||
|
||||
currRoot := roots[WorkingRoot]
|
||||
@@ -135,12 +136,13 @@ func checkoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, roots map[Roo
|
||||
head := roots[HeadRoot]
|
||||
|
||||
if len(docs) > 0 {
|
||||
currRootWithDocs, stagedWithDocs, err := getUpdatedWorkingAndStagedWithDocs(ctx, dEnv, currRoot, staged, head, docs)
|
||||
currRootWithDocs, stagedWithDocs, updatedDocs, err := getUpdatedWorkingAndStagedWithDocs(ctx, currRoot, staged, head, docs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currRoot = currRootWithDocs
|
||||
staged = stagedWithDocs
|
||||
docs = updatedDocs
|
||||
}
|
||||
|
||||
for _, tblName := range tbls {
|
||||
@@ -192,7 +194,7 @@ func checkoutTablesAndDocs(ctx context.Context, dEnv *env.DoltEnv, roots map[Roo
|
||||
return err
|
||||
}
|
||||
|
||||
return SaveDocsFromDocDetails(dEnv, docs)
|
||||
return dEnv.DocsReadWriter().WriteDocsToDisk(docs)
|
||||
}
|
||||
|
||||
func validateTablesExist(ctx context.Context, currRoot *doltdb.RootValue, unknown []string) error {
|
||||
|
||||
Vendored
-16
@@ -1,16 +0,0 @@
|
||||
// Copyright 2019 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package env provides access to get / set configuration and data repository state.
|
||||
package env
|
||||
+37
-75
@@ -15,88 +15,50 @@
|
||||
package env
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/filesys"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
)
|
||||
|
||||
type Docs []doltdb.DocDetails
|
||||
|
||||
var doltDocsColumns, _ = schema.NewColCollection(
|
||||
schema.NewColumn(doltdb.DocPkColumnName, schema.DocNameTag, types.StringKind, true, schema.NotNullConstraint{}),
|
||||
schema.NewColumn(doltdb.DocTextColumnName, schema.DocTextTag, types.StringKind, false),
|
||||
)
|
||||
var DoltDocsSchema = schema.MustSchemaFromCols(doltDocsColumns)
|
||||
|
||||
// AllValidDocDetails is a list of all valid docs with static fields DocPk and File. All other DocDetail fields
|
||||
// are dynamic and must be added, modified or removed as needed.
|
||||
var AllValidDocDetails = &Docs{
|
||||
doltdb.DocDetails{DocPk: doltdb.ReadmePk, File: ReadmeFile},
|
||||
doltdb.DocDetails{DocPk: doltdb.LicensePk, File: LicenseFile},
|
||||
}
|
||||
|
||||
func LoadDocs(fs filesys.ReadWriteFS) (Docs, error) {
|
||||
docsWithCurrentText := *AllValidDocDetails
|
||||
for i, val := range docsWithCurrentText {
|
||||
path := getDocFile(val.File)
|
||||
exists, isDir := fs.Exists(path)
|
||||
if exists && !isDir {
|
||||
data, err := fs.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
val.NewerText = data
|
||||
docsWithCurrentText[i] = val
|
||||
}
|
||||
// ResetWorkingDocsToStagedDocs resets the `dolt_docs` table on the working root to match the staged root.
|
||||
// If the `dolt_docs` table does not exist on the staged root, it will be removed from the working root.
|
||||
func ResetWorkingDocsToStagedDocs(ctx context.Context, ddb *doltdb.DoltDB, rsr RepoStateReader, rsw RepoStateWriter) error {
|
||||
wrkRoot, err := WorkingRoot(ctx, ddb, rsr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return docsWithCurrentText, nil
|
||||
}
|
||||
|
||||
func (docs Docs) Save(fs filesys.ReadWriteFS) error {
|
||||
for _, doc := range docs {
|
||||
if !IsValidDoc(doc.DocPk) {
|
||||
continue
|
||||
stgRoot, err := StagedRoot(ctx, ddb, rsr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stgDocTbl, stgDocsFound, err := stgRoot.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, wrkDocsFound, err := wrkRoot.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if wrkDocsFound && !stgDocsFound {
|
||||
newWrkRoot, err := wrkRoot.RemoveTables(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filePath := getDocFile(doc.File)
|
||||
if doc.NewerText != nil {
|
||||
err := fs.WriteFile(filePath, doc.NewerText)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := DeleteDoc(fs, doc.DocPk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = UpdateWorkingRoot(ctx, ddb, rsw, newWrkRoot)
|
||||
return err
|
||||
}
|
||||
|
||||
if stgDocsFound {
|
||||
newWrkRoot, err := wrkRoot.PutTable(ctx, doltdb.DocTableName, stgDocTbl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = UpdateWorkingRoot(ctx, ddb, rsw, newWrkRoot)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteDoc(fs filesys.ReadWriteFS, docName string) error {
|
||||
for _, doc := range *AllValidDocDetails {
|
||||
if doc.DocPk == docName {
|
||||
path := getDocFile(doc.File)
|
||||
exists, isDir := fs.Exists(path)
|
||||
if exists && !isDir {
|
||||
return fs.DeleteFile(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsValidDoc(docName string) bool {
|
||||
for _, doc := range *AllValidDocDetails {
|
||||
if doc.DocPk == docName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasDocFile(fs filesys.ReadWriteFS, file string) bool {
|
||||
exists, isDir := fs.Exists(getDocFile(file))
|
||||
return exists && !isDir
|
||||
}
|
||||
|
||||
+25
-347
@@ -32,13 +32,11 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/creds"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema/encoding"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/table"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/table/typed/noms"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/filesys"
|
||||
"github.com/dolthub/dolt/go/store/hash"
|
||||
"github.com/dolthub/dolt/go/store/types"
|
||||
@@ -57,7 +55,6 @@ var ErrPreexistingDoltDir = errors.New(".dolt dir already exists")
|
||||
var ErrStateUpdate = errors.New("error updating local data repo state")
|
||||
var ErrMarshallingSchema = errors.New("error marshalling schema")
|
||||
var ErrInvalidCredsFile = errors.New("invalid creds file")
|
||||
var ErrDocsUpdate = errors.New("error updating local docs")
|
||||
|
||||
// DoltEnv holds the state of the current environment used by the cli.
|
||||
type DoltEnv struct {
|
||||
@@ -69,7 +66,7 @@ type DoltEnv struct {
|
||||
RepoState *RepoState
|
||||
RSLoadErr error
|
||||
|
||||
Docs Docs
|
||||
Docs doltdocs.Docs
|
||||
DocsLoadErr error
|
||||
|
||||
DoltDB *doltdb.DoltDB
|
||||
@@ -84,7 +81,7 @@ type DoltEnv struct {
|
||||
func Load(ctx context.Context, hdp HomeDirProvider, fs filesys.Filesys, urlStr, version string) *DoltEnv {
|
||||
config, cfgErr := loadDoltCliConfig(hdp, fs)
|
||||
repoState, rsErr := LoadRepoState(fs)
|
||||
docs, docsErr := LoadDocs(fs)
|
||||
docs, docsErr := doltdocs.LoadDocs(fs)
|
||||
ddb, dbLoadErr := doltdb.LoadDoltDB(ctx, types.Format_Default, urlStr)
|
||||
|
||||
dEnv := &DoltEnv{
|
||||
@@ -177,23 +174,6 @@ func (dEnv *DoltEnv) HasLocalConfig() bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// GetDoc returns the path to the provided file, if it exists
|
||||
func (dEnv *DoltEnv) GetDoc(file string) string {
|
||||
if !hasDocFile(dEnv.FS, file) {
|
||||
return ""
|
||||
}
|
||||
return getDocFile(file)
|
||||
}
|
||||
|
||||
// GetLocalFileText returns a byte slice representing the contents of the provided file, if it exists
|
||||
func (dEnv *DoltEnv) GetLocalFileText(file string) ([]byte, error) {
|
||||
path := dEnv.GetDoc(file)
|
||||
if path != "" {
|
||||
return dEnv.FS.ReadFile(path)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (dEnv *DoltEnv) bestEffortDeleteAll(dir string) {
|
||||
fileToIsDir := make(map[string]bool)
|
||||
dEnv.FS.Iter(dir, false, func(path string, size int64, isDir bool) (stop bool) {
|
||||
@@ -395,10 +375,6 @@ func (r *repoStateReader) GetMergeCommit() string {
|
||||
return r.dEnv.RepoState.Merge.Commit
|
||||
}
|
||||
|
||||
func (r *repoStateReader) GetAllValidDocDetails() ([]doltdb.DocDetails, error) {
|
||||
return r.dEnv.GetAllValidDocDetails()
|
||||
}
|
||||
|
||||
func (dEnv *DoltEnv) RepoStateReader() RepoStateReader {
|
||||
return &repoStateReader{dEnv}
|
||||
}
|
||||
@@ -433,45 +409,40 @@ func (r *repoStateWriter) ClearMerge() error {
|
||||
return r.dEnv.RepoState.ClearMerge(r.dEnv.FS)
|
||||
}
|
||||
|
||||
func (r *repoStateWriter) PutDocsToWorking(ctx context.Context, docDetails []doltdb.DocDetails) error {
|
||||
return r.dEnv.PutDocsToWorking(ctx, docDetails)
|
||||
}
|
||||
|
||||
func (r *repoStateWriter) ResetWorkingDocsToStagedDos(ctx context.Context) error {
|
||||
return r.dEnv.ResetWorkingDocsToStagedDocs(ctx)
|
||||
}
|
||||
|
||||
func (dEnv *DoltEnv) RepoStateWriter() RepoStateWriter {
|
||||
return &repoStateWriter{dEnv}
|
||||
}
|
||||
|
||||
type docsReadWriter struct {
|
||||
dEnv *DoltEnv
|
||||
FS filesys.Filesys
|
||||
}
|
||||
|
||||
func (d *docsReadWriter) GetAllValidDocDetails() ([]doltdb.DocDetails, error) {
|
||||
return d.dEnv.GetAllValidDocDetails()
|
||||
// GetDocsOnDisk reads the filesystem and returns all docs.
|
||||
func (d *docsReadWriter) GetDocsOnDisk(docNames ...string) (doltdocs.Docs, error) {
|
||||
if docNames != nil {
|
||||
ret := make(doltdocs.Docs, len(docNames))
|
||||
|
||||
for i, name := range docNames {
|
||||
doc, err := doltdocs.GetDoc(d.FS, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret[i] = doc
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
return doltdocs.GetSupportedDocs(d.FS)
|
||||
}
|
||||
|
||||
func (d *docsReadWriter) PutDocsToWorking(ctx context.Context, docDetails []doltdb.DocDetails) error {
|
||||
return d.dEnv.PutDocsToWorking(ctx, docDetails)
|
||||
}
|
||||
|
||||
func (d *docsReadWriter) PutDocsToStaged(ctx context.Context, docDetails []doltdb.DocDetails) (*doltdb.RootValue, error) {
|
||||
return d.dEnv.PutDocsToStaged(ctx, docDetails)
|
||||
}
|
||||
|
||||
func (d *docsReadWriter) ResetWorkingDocsToStagedDocs(ctx context.Context) error {
|
||||
return d.dEnv.ResetWorkingDocsToStagedDocs(ctx)
|
||||
}
|
||||
|
||||
// GetDocDetail returns the details of a specific document passed as docName.
|
||||
func (d *docsReadWriter) GetDocDetail(docName string) (doc doltdb.DocDetails, err error) {
|
||||
return d.dEnv.GetDocDetail(docName)
|
||||
// WriteDocsToDisk creates or updates the dolt_docs table with docs.
|
||||
func (d *docsReadWriter) WriteDocsToDisk(docs doltdocs.Docs) error {
|
||||
return docs.Save(d.FS)
|
||||
}
|
||||
|
||||
func (dEnv *DoltEnv) DocsReadWriter() DocsReadWriter {
|
||||
return &docsReadWriter{dEnv}
|
||||
return &docsReadWriter{dEnv.FS}
|
||||
}
|
||||
|
||||
func (dEnv *DoltEnv) HeadRoot(ctx context.Context) (*doltdb.RootValue, error) {
|
||||
@@ -896,296 +867,3 @@ func (dEnv *DoltEnv) GetUserHomeDir() (string, error) {
|
||||
func (dEnv *DoltEnv) TempTableFilesDir() string {
|
||||
return mustAbs(dEnv, dEnv.GetDoltDir(), tempTablesDir)
|
||||
}
|
||||
|
||||
func (dEnv *DoltEnv) GetAllValidDocDetails() (docs []doltdb.DocDetails, err error) {
|
||||
docs = []doltdb.DocDetails{}
|
||||
for _, doc := range *AllValidDocDetails {
|
||||
newerText, err := dEnv.GetLocalFileText(doc.File)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
doc.NewerText = newerText
|
||||
docs = append(docs, doc)
|
||||
}
|
||||
return docs, nil
|
||||
}
|
||||
|
||||
func (dEnv *DoltEnv) GetDocDetail(docName string) (doc doltdb.DocDetails, err error) {
|
||||
for _, doc := range *AllValidDocDetails {
|
||||
if doc.DocPk == docName {
|
||||
newerText, err := dEnv.GetLocalFileText(doc.File)
|
||||
if err != nil {
|
||||
return doltdb.DocDetails{}, err
|
||||
}
|
||||
doc.NewerText = newerText
|
||||
return doc, nil
|
||||
}
|
||||
}
|
||||
return doltdb.DocDetails{}, err
|
||||
}
|
||||
|
||||
// WorkingRootWithDocs returns a copy of the working root that has been updated with the Dolt docs from the file system.
|
||||
func (dEnv *DoltEnv) WorkingRootWithDocs(ctx context.Context) (*doltdb.RootValue, error) {
|
||||
dds, err := dEnv.GetAllValidDocDetails()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wr, err := dEnv.WorkingRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dEnv.GetUpdatedRootWithDocs(ctx, wr, dds)
|
||||
}
|
||||
|
||||
// GetUpdatedRootWithDocs adds, updates or removes the `dolt_docs` table on the provided root. The table will be added or updated
|
||||
// When at least one doc.NewerText != nil. If the `dolt_docs` table exists and every doc.NewerText == nil, the table will be removed.
|
||||
// If no docDetails are provided, we put all valid docs to the working root.
|
||||
func (dEnv *DoltEnv) GetUpdatedRootWithDocs(ctx context.Context, root *doltdb.RootValue, docDetails []doltdb.DocDetails) (*doltdb.RootValue, error) {
|
||||
docTbl, found, err := root.GetTable(ctx, doltdb.DocTableName)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
docDetails, err = getDocDetails(dEnv, docDetails)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if found {
|
||||
return updateDocsOnRoot(ctx, dEnv, root, docTbl, docDetails)
|
||||
}
|
||||
return createDocsTableOnRoot(ctx, dEnv, root, docDetails)
|
||||
}
|
||||
|
||||
// PutDocsToWorking adds, updates or removes the `dolt_docs` table on the working root using the provided docDetails.
|
||||
func (dEnv *DoltEnv) PutDocsToWorking(ctx context.Context, docDetails []doltdb.DocDetails) error {
|
||||
wrkRoot, err := dEnv.WorkingRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootWithDocs, err := dEnv.GetUpdatedRootWithDocs(ctx, wrkRoot, docDetails)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dEnv.UpdateWorkingRoot(ctx, rootWithDocs)
|
||||
}
|
||||
|
||||
// PutDocsToStaged adds, updates or removes the `dolt_docs` table on the staged root using the provided docDetails.
|
||||
func (dEnv *DoltEnv) PutDocsToStaged(ctx context.Context, docDetails []doltdb.DocDetails) (*doltdb.RootValue, error) {
|
||||
stgRoot, err := dEnv.StagedRoot(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rootWithDocs, err := dEnv.GetUpdatedRootWithDocs(ctx, stgRoot, docDetails)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = dEnv.UpdateStagedRoot(ctx, rootWithDocs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return createDocsTableOnRoot(ctx, dEnv, rootWithDocs, docDetails)
|
||||
}
|
||||
|
||||
func getDocDetails(dEnv *DoltEnv, docDetails []doltdb.DocDetails) ([]doltdb.DocDetails, error) {
|
||||
if docDetails == nil {
|
||||
docs, err := dEnv.GetAllValidDocDetails()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return docs, nil
|
||||
}
|
||||
return docDetails, nil
|
||||
}
|
||||
|
||||
// ResetWorkingDocsToStagedDocs resets the `dolt_docs` table on the working root to match the staged root.
|
||||
// If the `dolt_docs` table does not exist on the staged root, it will be removed from the working root.
|
||||
func (dEnv *DoltEnv) ResetWorkingDocsToStagedDocs(ctx context.Context) error {
|
||||
wrkRoot, err := dEnv.WorkingRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stgRoot, err := dEnv.StagedRoot(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stgDocTbl, stgDocsFound, err := stgRoot.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, wrkDocsFound, err := wrkRoot.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if wrkDocsFound && !stgDocsFound {
|
||||
newWrkRoot, err := wrkRoot.RemoveTables(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dEnv.UpdateWorkingRoot(ctx, newWrkRoot)
|
||||
}
|
||||
|
||||
if stgDocsFound {
|
||||
newWrkRoot, err := wrkRoot.PutTable(ctx, doltdb.DocTableName, stgDocTbl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dEnv.UpdateWorkingRoot(ctx, newWrkRoot)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateDocsOnRoot(ctx context.Context, dEnv *DoltEnv, root *doltdb.RootValue, docTbl *doltdb.Table, docDetails []doltdb.DocDetails) (*doltdb.RootValue, error) {
|
||||
m, err := docTbl.GetRowData(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sch, err := docTbl.GetSchema(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
me := m.Edit()
|
||||
for _, doc := range docDetails {
|
||||
key, err := doltdb.DocTblKeyFromName(docTbl.Format(), doc.DocPk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
docRow, exists, err := table.GetRow(ctx, docTbl, sch, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if exists && doc.NewerText == nil {
|
||||
me = me.Remove(docRow.NomsMapKey(sch))
|
||||
} else if doc.NewerText != nil {
|
||||
docTaggedVals := row.TaggedValues{
|
||||
schema.DocNameTag: types.String(doc.DocPk),
|
||||
schema.DocTextTag: types.String(doc.NewerText),
|
||||
}
|
||||
docRow, err = row.New(types.Format_7_18, sch, docTaggedVals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
me = me.Set(docRow.NomsMapKey(sch), docRow.NomsMapValue(sch))
|
||||
}
|
||||
}
|
||||
updatedMap, err := me.Map(ctx)
|
||||
if updatedMap.Len() == 0 {
|
||||
return root.RemoveTables(ctx, doltdb.DocTableName)
|
||||
}
|
||||
docTbl, err = docTbl.UpdateRows(ctx, updatedMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return root.PutTable(ctx, doltdb.DocTableName, docTbl)
|
||||
}
|
||||
|
||||
func createDocsTableOnRoot(ctx context.Context, dEnv *DoltEnv, root *doltdb.RootValue, docDetails []doltdb.DocDetails) (*doltdb.RootValue, error) {
|
||||
imt := table.NewInMemTable(DoltDocsSchema)
|
||||
|
||||
createTable := false
|
||||
for _, doc := range docDetails {
|
||||
if doc.NewerText != nil {
|
||||
createTable = true
|
||||
docTaggedVals := row.TaggedValues{
|
||||
schema.DocNameTag: types.String(doc.DocPk),
|
||||
schema.DocTextTag: types.String(doc.NewerText),
|
||||
}
|
||||
|
||||
docRow, err := row.New(types.Format_7_18, DoltDocsSchema, docTaggedVals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = imt.AppendRow(docRow)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if createTable {
|
||||
rd := table.NewInMemTableReader(imt)
|
||||
wr := noms.NewNomsMapCreator(context.Background(), dEnv.DoltDB.ValueReadWriter(), DoltDocsSchema)
|
||||
|
||||
_, _, err := table.PipeRows(context.Background(), rd, wr, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rd.Close(context.Background())
|
||||
wr.Close(context.Background())
|
||||
|
||||
vrw := root.VRW()
|
||||
schVal, err := encoding.MarshalSchemaAsNomsValue(ctx, vrw, wr.GetSchema())
|
||||
|
||||
if err != nil {
|
||||
return nil, ErrMarshallingSchema
|
||||
}
|
||||
|
||||
empty, err := types.NewMap(ctx, root.VRW())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newDocsTbl, err := doltdb.NewTable(ctx, root.VRW(), schVal, wr.GetMap(), empty)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return root.PutTable(ctx, doltdb.DocTableName, newDocsTbl)
|
||||
}
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
//UpdateFSDocsToRootDocs updates the provided docs from the root value, and then saves them to the filesystem.
|
||||
// If docs == nil, all valid docs will be retrieved and written.
|
||||
func (dEnv *DoltEnv) UpdateFSDocsToRootDocs(ctx context.Context, root *doltdb.RootValue, docs Docs) error {
|
||||
docs, err := dEnv.GetDocsWithNewerTextFromRoot(ctx, root, docs)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return docs.Save(dEnv.FS)
|
||||
}
|
||||
|
||||
// GetDocsWithNewerTextFromRoot returns Docs with the NewerText value(s) from the provided root. If docs are provided,
|
||||
// only those docs will be retrieved and returned. Otherwise, all valid doc details are returned with the updated NewerText.
|
||||
func (dEnv *DoltEnv) GetDocsWithNewerTextFromRoot(ctx context.Context, root *doltdb.RootValue, docs Docs) (Docs, error) {
|
||||
docTbl, docTblFound, err := root.GetTable(ctx, doltdb.DocTableName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sch schema.Schema
|
||||
if docTblFound {
|
||||
docSch, err := docTbl.GetSchema(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sch = docSch
|
||||
}
|
||||
|
||||
if docs == nil {
|
||||
docs = *AllValidDocDetails
|
||||
}
|
||||
|
||||
for i, doc := range docs {
|
||||
doc, err = doltdb.AddNewerTextToDocFromTbl(ctx, docTbl, &sch, doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs[i] = doc
|
||||
}
|
||||
return docs, nil
|
||||
}
|
||||
|
||||
+3
-2
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/filesys"
|
||||
"github.com/dolthub/dolt/go/store/hash"
|
||||
@@ -175,8 +176,8 @@ func TestInitRepo(t *testing.T) {
|
||||
t.Error("Failed to get staged root value.")
|
||||
}
|
||||
|
||||
for _, doc := range *AllValidDocDetails {
|
||||
docPath := getDocFile(doc.File)
|
||||
for _, doc := range doltdocs.SupportedDocs {
|
||||
docPath := doltdocs.GetDocFilePath(doc.File)
|
||||
if len(docPath) > 0 && !strings.Contains(doc.File, docPath) {
|
||||
t.Error("Doc file path should exist: ", doc.File)
|
||||
}
|
||||
|
||||
Vendored
-7
@@ -31,9 +31,6 @@ const (
|
||||
globalConfig = "config_global.json"
|
||||
|
||||
repoStateFile = "repo_state.json"
|
||||
|
||||
ReadmeFile = "../README.md"
|
||||
LicenseFile = "../LICENSE.md"
|
||||
)
|
||||
|
||||
// HomeDirProvider is a function that returns the users home directory. This is where global dolt state is stored for
|
||||
@@ -90,7 +87,3 @@ func getHomeDir(hdp HomeDirProvider) (string, error) {
|
||||
}
|
||||
return homeDir, nil
|
||||
}
|
||||
|
||||
func getDocFile(filename string) string {
|
||||
return filepath.Join(dbfactory.DoltDir, filename)
|
||||
}
|
||||
|
||||
+5
-5
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/filesys"
|
||||
"github.com/dolthub/dolt/go/store/hash"
|
||||
@@ -43,11 +44,10 @@ type RepoStateWriter interface {
|
||||
}
|
||||
|
||||
type DocsReadWriter interface {
|
||||
GetAllValidDocDetails() ([]doltdb.DocDetails, error)
|
||||
PutDocsToWorking(ctx context.Context, docDetails []doltdb.DocDetails) error
|
||||
PutDocsToStaged(ctx context.Context, docDetails []doltdb.DocDetails) (*doltdb.RootValue, error)
|
||||
ResetWorkingDocsToStagedDocs(ctx context.Context) error
|
||||
GetDocDetail(docName string) (doc doltdb.DocDetails, err error)
|
||||
// GetDocsOnDisk returns the docs in the filesytem optionally filtered by docNames.
|
||||
GetDocsOnDisk(docNames ...string) (doltdocs.Docs, error)
|
||||
// WriteDocsToDisk updates the documents stored in the filesystem with the contents in docs.
|
||||
WriteDocsToDisk(docs doltdocs.Docs) error
|
||||
}
|
||||
|
||||
type DbData struct {
|
||||
|
||||
@@ -871,7 +871,7 @@ func GetTablesInConflict(ctx context.Context, ddb *doltdb.DoltDB, rsr env.RepoSt
|
||||
}
|
||||
|
||||
func GetDocsInConflict(ctx context.Context, ddb *doltdb.DoltDB, rsr env.RepoStateReader, drw env.DocsReadWriter) (*diff.DocDiffs, error) {
|
||||
docDetails, err := drw.GetAllValidDocDetails()
|
||||
docs, err := drw.GetDocsOnDisk()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -881,5 +881,5 @@ func GetDocsInConflict(ctx context.Context, ddb *doltdb.DoltDB, rsr env.RepoStat
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return diff.NewDocDiffs(ctx, workingRoot, nil, docDetails)
|
||||
return diff.NewDocDiffs(ctx, workingRoot, nil, docs)
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/store/hash"
|
||||
)
|
||||
|
||||
@@ -100,12 +100,12 @@ func AllBranches(ctx context.Context, dEnv *env.DoltEnv, replay ReplayCommitFn,
|
||||
return err
|
||||
}
|
||||
|
||||
return rebaseRefs(ctx, dEnv, replay, nerf, branches...)
|
||||
return rebaseRefs(ctx, dEnv.DbData(), replay, nerf, branches...)
|
||||
}
|
||||
|
||||
// CurrentBranch rewrites the history of the current branch using the |replay| function.
|
||||
func CurrentBranch(ctx context.Context, dEnv *env.DoltEnv, replay ReplayCommitFn, nerf NeedsRebaseFn) error {
|
||||
return rebaseRefs(ctx, dEnv, replay, nerf, dEnv.RepoState.CWBHeadRef())
|
||||
return rebaseRefs(ctx, dEnv.DbData(), replay, nerf, dEnv.RepoState.CWBHeadRef())
|
||||
}
|
||||
|
||||
// AllBranchesByRoots rewrites the history of all branches in the repo using the |replay| function.
|
||||
@@ -116,19 +116,23 @@ func AllBranchesByRoots(ctx context.Context, dEnv *env.DoltEnv, replay ReplayRoo
|
||||
}
|
||||
|
||||
replayCommit := wrapReplayRootFn(replay)
|
||||
return rebaseRefs(ctx, dEnv, replayCommit, nerf, branches...)
|
||||
return rebaseRefs(ctx, dEnv.DbData(), replayCommit, nerf, branches...)
|
||||
}
|
||||
|
||||
// CurrentBranchByRoot rewrites the history of the current branch using the |replay| function.
|
||||
func CurrentBranchByRoot(ctx context.Context, dEnv *env.DoltEnv, replay ReplayRootFn, nerf NeedsRebaseFn) error {
|
||||
replayCommit := wrapReplayRootFn(replay)
|
||||
return rebaseRefs(ctx, dEnv, replayCommit, nerf, dEnv.RepoState.CWBHeadRef())
|
||||
return rebaseRefs(ctx, dEnv.DbData(), replayCommit, nerf, dEnv.RepoState.CWBHeadRef())
|
||||
}
|
||||
|
||||
func rebaseRefs(ctx context.Context, dEnv *env.DoltEnv, replay ReplayCommitFn, nerf NeedsRebaseFn, refs ...ref.DoltRef) error {
|
||||
ddb := dEnv.DoltDB
|
||||
cwbRef := dEnv.RepoState.CWBHeadRef()
|
||||
dd, err := dEnv.GetAllValidDocDetails()
|
||||
func rebaseRefs(ctx context.Context, dbData env.DbData, replay ReplayCommitFn, nerf NeedsRebaseFn, refs ...ref.DoltRef) error {
|
||||
ddb := dbData.Ddb
|
||||
rsr := dbData.Rsr
|
||||
rsw := dbData.Rsw
|
||||
drw := dbData.Drw
|
||||
|
||||
cwbRef := rsr.CWBHeadRef()
|
||||
dd, err := drw.GetDocsOnDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -165,7 +169,7 @@ func rebaseRefs(ctx context.Context, dEnv *env.DoltEnv, replay ReplayCommitFn, n
|
||||
}
|
||||
}
|
||||
|
||||
cm, err := dEnv.DoltDB.ResolveRef(ctx, cwbRef)
|
||||
cm, err := ddb.ResolveRef(ctx, cwbRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -175,22 +179,21 @@ func rebaseRefs(ctx context.Context, dEnv *env.DoltEnv, replay ReplayCommitFn, n
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = dEnv.UpdateStagedRoot(ctx, r)
|
||||
_, err = doltdocs.UpdateRootWithDocs(ctx, r, dd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = dEnv.UpdateWorkingRoot(ctx, r)
|
||||
_, err = env.UpdateStagedRoot(ctx, ddb, rsw, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = dEnv.PutDocsToWorking(ctx, dd)
|
||||
_, err = env.UpdateWorkingRoot(ctx, ddb, rsw, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = dEnv.PutDocsToStaged(ctx, dd)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
@@ -982,7 +983,7 @@ func TestAlterSystemTables(t *testing.T) {
|
||||
})
|
||||
|
||||
dtestutils.CreateTestTable(t, dEnv, "dolt_docs",
|
||||
env.DoltDocsSchema,
|
||||
doltdocs.DoltDocsSchema,
|
||||
NewRow(types.String("LICENSE.md"), types.String("A license")))
|
||||
dtestutils.CreateTestTable(t, dEnv, doltdb.DoltQueryCatalogTableName,
|
||||
dtables.DoltQueryCatalogSchema,
|
||||
|
||||
@@ -23,8 +23,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
. "github.com/dolthub/dolt/go/libraries/doltcore/sql/sqltestutil"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables"
|
||||
@@ -194,7 +194,7 @@ var systemTableDeleteTests = []DeleteTest{
|
||||
{
|
||||
Name: "delete dolt_docs",
|
||||
AdditionalSetup: CreateTableFn("dolt_docs",
|
||||
env.DoltDocsSchema,
|
||||
doltdocs.DoltDocsSchema,
|
||||
NewRow(types.String("LICENSE.md"), types.String("A license"))),
|
||||
DeleteQuery: "delete from dolt_docs",
|
||||
ExpectedErr: "cannot delete from table",
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
@@ -400,7 +401,7 @@ var systemTableInsertTests = []InsertTest{
|
||||
{
|
||||
Name: "insert into dolt_docs",
|
||||
AdditionalSetup: CreateTableFn("dolt_docs",
|
||||
env.DoltDocsSchema,
|
||||
doltdocs.DoltDocsSchema,
|
||||
NewRow(types.String("LICENSE.md"), types.String("A license"))),
|
||||
InsertQuery: "insert into dolt_docs (doc_name, doc_text) values ('README.md', 'Some text')",
|
||||
ExpectedErr: "cannot insert into table",
|
||||
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
. "github.com/dolthub/dolt/go/libraries/doltcore/sql/sqltestutil"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables"
|
||||
@@ -256,7 +256,7 @@ var systemTableReplaceTests = []ReplaceTest{
|
||||
{
|
||||
Name: "replace into dolt_docs",
|
||||
AdditionalSetup: CreateTableFn("dolt_docs",
|
||||
env.DoltDocsSchema,
|
||||
doltdocs.DoltDocsSchema,
|
||||
NewRow(types.String("LICENSE.md"), types.String("A license"))),
|
||||
ReplaceQuery: "replace into dolt_docs (doc_name, doc_text) values ('README.md', 'Some text')",
|
||||
ExpectedErr: "cannot insert into table",
|
||||
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/envtestutils"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/row"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
@@ -1465,15 +1465,15 @@ var systemTableSelectTests = []SelectTest{
|
||||
{
|
||||
Name: "select from dolt_docs",
|
||||
AdditionalSetup: CreateTableFn("dolt_docs",
|
||||
env.DoltDocsSchema,
|
||||
NewRowWithSchema(env.DoltDocsSchema,
|
||||
doltdocs.DoltDocsSchema,
|
||||
NewRowWithSchema(doltdocs.DoltDocsSchema,
|
||||
types.String("LICENSE.md"),
|
||||
types.String("A license")),
|
||||
),
|
||||
Query: "select * from dolt_docs",
|
||||
ExpectedRows: ToSqlRows(CompressSchema(env.DoltDocsSchema),
|
||||
ExpectedRows: ToSqlRows(CompressSchema(doltdocs.DoltDocsSchema),
|
||||
NewRow(types.String("LICENSE.md"), types.String("A license"))),
|
||||
ExpectedSchema: CompressSchema(env.DoltDocsSchema),
|
||||
ExpectedSchema: CompressSchema(doltdocs.DoltDocsSchema),
|
||||
},
|
||||
{
|
||||
Name: "select from dolt_query_catalog",
|
||||
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
|
||||
. "github.com/dolthub/dolt/go/libraries/doltcore/sql/sqltestutil"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables"
|
||||
@@ -378,7 +378,7 @@ var systemTableUpdateTests = []UpdateTest{
|
||||
{
|
||||
Name: "update dolt_docs",
|
||||
AdditionalSetup: CreateTableFn("dolt_docs",
|
||||
env.DoltDocsSchema,
|
||||
doltdocs.DoltDocsSchema,
|
||||
NewRow(types.String("LICENSE.md"), types.String("A license"))),
|
||||
UpdateQuery: "update dolt_docs set doc_text = 'Some text')",
|
||||
ExpectedErr: "cannot insert into table",
|
||||
|
||||
Reference in New Issue
Block a user