added temp migration environment

This commit is contained in:
Andy Arthur
2022-07-21 14:44:44 -07:00
parent 226da75db3
commit c95153ca6c
6 changed files with 243 additions and 17 deletions
+22 -2
View File
@@ -20,8 +20,10 @@ import (
"github.com/fatih/color"
"github.com/dolthub/dolt/go/cmd/dolt/cli"
"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/env"
"github.com/dolthub/dolt/go/libraries/doltcore/migrate"
"github.com/dolthub/dolt/go/libraries/utils/argparser"
)
@@ -36,7 +38,7 @@ const (
var migrateDocs = cli.CommandDocumentationContent{
ShortDesc: "Executes a database migration to use the latest Dolt data format.",
LongDesc: `Migrate is a multi-purpose command to update the data format of a Dolt database. Over time, development
on Dolt requires changes to the on-disk data format. These changes are necessary to improve Database performance amd
on Dolt requires changes to the on-disk data format. These changes are necessary to improve Database performance and
correctness. Migrating to the latest format is therefore necessary for compatibility with the latest Dolt clients, and
to take advantage of the newly released Dolt features.`,
@@ -76,7 +78,7 @@ func (cmd MigrateCmd) EventType() eventsapi.ClientEventType {
// Exec executes the command
func (cmd MigrateCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
ap := cmd.ArgParser()
help, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, migrateDocs, ap))
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, migrateDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
if apr.Contains(migratePushFlag) && apr.Contains(migratePullFlag) {
@@ -84,5 +86,23 @@ func (cmd MigrateCmd) Exec(ctx context.Context, commandStr string, args []string
return 1
}
if err := MigrateDatabase(ctx, dEnv); err != nil {
verr := errhand.BuildDError("migration failed").AddCause(err).Build()
return HandleVErrAndExitCode(verr, usage)
}
return 0
}
func MigrateDatabase(ctx context.Context, dEnv *env.DoltEnv) error {
menv, err := migrate.NewEnvironment(ctx, dEnv)
if err != nil {
return err
}
err = migrate.TraverseDAG(ctx, menv.Migration.DoltDB, menv.Existing.DoltDB)
if err != nil {
return err
}
return migrate.SwapChunkstores(ctx, menv.Migration, "")
}
@@ -0,0 +1,153 @@
// Copyright 2022 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 migrate
import (
"context"
"fmt"
"path/filepath"
"strings"
"time"
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/utils/earl"
"github.com/dolthub/dolt/go/libraries/utils/filesys"
"github.com/dolthub/dolt/go/store/types"
"github.com/dolthub/dolt/go/libraries/doltcore/env"
)
const (
doltDir = dbfactory.DoltDir
nomsDir = dbfactory.DataDir
)
var targetFormat = types.Format_DOLT_DEV
type Environment struct {
Migration *env.DoltEnv
Existing *env.DoltEnv
}
func NewEnvironment(ctx context.Context, existing *env.DoltEnv) (Environment, error) {
mfs, err := getMigrateFS(existing.FS)
if err != nil {
return Environment{}, err
}
if err = InitMigrationDB(ctx, existing.FS, mfs); err != nil {
return Environment{}, err
}
mdb, err := doltdb.LoadDoltDB(ctx, targetFormat, doltdb.LocalDirDoltDB, mfs)
if err != nil {
return Environment{}, err
}
config, err := env.LoadDoltCliConfig(env.GetCurrentUserHomeDir, mfs)
if err != nil {
return Environment{}, err
}
migration := &env.DoltEnv{
Version: existing.Version,
Config: config,
RepoState: existing.RepoState,
DoltDB: mdb,
FS: mfs,
//urlStr: urlStr,
//hdp: hdp,
}
return Environment{
Migration: migration,
Existing: existing,
}, nil
}
func SwapChunkstores(ctx context.Context, migration *env.DoltEnv, dest string) error {
return nil
}
func InitMigrationDB(ctx context.Context, src, dest filesys.Filesys) (err error) {
base, err := src.Abs(".")
if err != nil {
return err
}
ierr := src.Iter(doltDir, true, func(path string, size int64, isDir bool) (stop bool) {
if isDir {
err = dest.MkDirs(path)
stop = err != nil
return
}
if strings.Contains(path, nomsDir) {
return
}
path, err = filepath.Rel(base, path)
if err != nil {
stop = true
return
}
if err = filesys.CopyFile(path, path, src, dest); err != nil {
stop = true
return
}
return
})
if ierr != nil {
return ierr
}
if err != nil {
return err
}
dd, err := dest.Abs(filepath.Join(doltDir, nomsDir))
if err != nil {
return err
}
if err = dest.MkDirs(dd); err != nil {
return err
}
u, err := earl.Parse(dd)
if err != nil {
return err
}
_, _, _, err = dbfactory.FileFactory{}.CreateDB(ctx, targetFormat, u, nil)
return
}
func getMigrateFS(existing filesys.Filesys) (filesys.Filesys, error) {
uniq := fmt.Sprintf("dolt_migration_%d", time.Now().Unix())
tmpPath := filepath.Join(existing.TempDir(), uniq)
if err := existing.MkDirs(tmpPath); err != nil {
return nil, err
}
mfs, err := filesys.LocalFilesysWithWorkingDir(tmpPath)
if err != nil {
return nil, err
}
if err = mfs.MkDirs(doltDir); err != nil {
return nil, err
}
return mfs, nil
}
+2 -2
View File
@@ -20,10 +20,10 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
)
func MigrateCommit(ctx context.Context, old *doltdb.Commit, prog Progress) error {
func MigrateCommit(ctx context.Context, old *doltdb.Commit, new *doltdb.DoltDB, prog Progress) error {
return nil
}
func MigrateRoot(ctx context.Context, old *doltdb.RootValue) (*doltdb.RootValue, error) {
func MigrateRoot(ctx context.Context, old *doltdb.RootValue, new *doltdb.DoltDB) (*doltdb.RootValue, error) {
return old, nil
}
@@ -23,34 +23,34 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
)
func TraverseDAG(ctx context.Context, ddb *doltdb.DoltDB) (Progress, error) {
heads, err := ddb.GetHeadRefs(ctx)
func TraverseDAG(ctx context.Context, old, new *doltdb.DoltDB) error {
heads, err := old.GetHeadRefs(ctx)
if err != nil {
return nil, err
return err
}
prog := newProgress()
for i := range heads {
if err = TraverseHistory(ctx, heads[i], prog); err != nil {
return nil, err
if err = TraverseRefHistory(ctx, heads[i], new, prog); err != nil {
return err
}
}
return prog, nil
}
func TraverseHistory(ctx context.Context, r ref.DoltRef, prog Progress) error {
return nil
}
func TraverseTagHistory(ctx context.Context, tag *doltdb.Tag, prog Progress) error {
func TraverseRefHistory(ctx context.Context, r ref.DoltRef, new *doltdb.DoltDB, prog Progress) error {
return nil
}
func TraverseWorkingSetHistory(ctx context.Context, ws doltdb.WorkingSet, prog Progress) error {
func TraverseTagHistory(ctx context.Context, tag *doltdb.Tag, new *doltdb.DoltDB, prog Progress) error {
return nil
}
func TraverseCommitHistory(ctx context.Context, cm *doltdb.Commit, prog Progress) error {
func TraverseWorkingSetHistory(ctx context.Context, ws doltdb.WorkingSet, new *doltdb.DoltDB, prog Progress) error {
return nil
}
func TraverseCommitHistory(ctx context.Context, cm *doltdb.Commit, new *doltdb.DoltDB, prog Progress) error {
for {
ph, err := cm.ParentHashes(ctx)
if err != nil {
@@ -63,7 +63,7 @@ func TraverseCommitHistory(ctx context.Context, cm *doltdb.Commit, prog Progress
}
if idx < 0 {
// parents for |cm| are done, migrate |cm|
if err = MigrateCommit(ctx, cm, prog); err != nil {
if err = MigrateCommit(ctx, cm, new, prog); err != nil {
return err
}
// pop the stack, traverse upwards
+15
View File
@@ -114,3 +114,18 @@ func UnmarshalJSONFile(fs ReadableFS, path string, dest interface{}) error {
return json.Unmarshal(data, dest)
}
func CopyFile(srcPath, destPath string, srcFS, destFS Filesys) (err error) {
rd, err := srcFS.OpenForRead(srcPath)
if err != nil {
return err
}
wr, err := destFS.OpenForWrite(destPath, os.ModePerm)
if err != nil {
return err
}
_, err = io.Copy(wr, rd)
return
}
+38
View File
@@ -537,6 +537,44 @@ func (fs *InMemFS) MoveFile(srcPath, destPath string) error {
return os.ErrNotExist
}
func (fs *InMemFS) CopyFile(srcPath, destPath string) error {
fs.rwLock.Lock()
defer fs.rwLock.Unlock()
srcPath = fs.getAbsPath(srcPath)
destPath = fs.getAbsPath(destPath)
if exists, destIsDir := fs.exists(destPath); exists && destIsDir {
return ErrIsDir
}
if obj, ok := fs.objs[srcPath]; ok {
if obj.isDir() {
return ErrIsDir
}
destDir := filepath.Dir(destPath)
destParentDir, err := fs.mkDirs(destDir)
if err != nil {
return err
}
destData := make([]byte, len(obj.(*memFile).data))
copy(destData, obj.(*memFile).data)
now := InMemNowFunc()
destObj := &memFile{destPath, destData, destParentDir, now}
fs.objs[destPath] = destObj
destParentDir.objs[destPath] = destObj
destParentDir.time = now
return nil
}
return os.ErrNotExist
}
// converts a path to an absolute path. If it's already an absolute path the input path will be returned unaltered
func (fs *InMemFS) Abs(path string) (string, error) {
path = fs.pathToNative(path)