mirror of
https://github.com/dolthub/dolt.git
synced 2026-04-27 07:26:31 -05:00
added temp migration environment
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+13
-13
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user