fix dolt pull --force to work properly

This commit is contained in:
Stephanie You
2023-10-08 20:55:19 -07:00
parent 6f095c5750
commit 5ca6a19962
5 changed files with 112 additions and 62 deletions

View File

@@ -21,6 +21,7 @@ import (
"strings"
"time"
"github.com/dolthub/dolt/go/store/util/outputpager"
"github.com/dolthub/go-mysql-server/sql"
"github.com/gocraft/dbr/v2"
"github.com/gocraft/dbr/v2/dialect"
@@ -133,10 +134,36 @@ func (cmd PullCmd) Exec(ctx context.Context, commandStr string, args []string, d
if remoteHashErr != nil {
cli.Println("pull finished, but failed to get hash of remote ref")
}
success := printMergeStats(rows, apr, queryist, sqlCtx, usage, remoteHash, remoteHashErr)
if success == 1 {
errChan <- errors.New(" ") //return a non-nil error for the correct exit code but no further messages to print
return
if apr.Contains(cli.ForceFlag) {
headHash, headhHashErr := getHashOf(queryist, sqlCtx, "HEAD")
if headhHashErr != nil {
cli.Println("merge finished, but failed to get hash of HEAD")
cli.Println(headhHashErr.Error())
}
if remoteHashErr == nil && headhHashErr == nil {
cli.Println("Updating", headHash+".."+remoteHash)
}
commit, err := getCommitInfo(queryist, sqlCtx, "HEAD")
if err != nil {
cli.Println("merge finished, but failed to get commit info")
cli.Println(err.Error())
return
}
if cli.ExecuteWithStdioRestored != nil {
cli.ExecuteWithStdioRestored(func() {
pager := outputpager.Start()
defer pager.Stop()
PrintCommitInfo(pager, 0, false, "auto", commit)
})
}
} else {
success := printMergeStats(rows, apr, queryist, sqlCtx, usage, remoteHash, remoteHashErr)
if success == 1 {
errChan <- errors.New(" ") //return a non-nil error for the correct exit code but no further messages to print
return
}
}
}()

View File

@@ -81,16 +81,6 @@ func WithSquash(squash bool) MergeSpecOpt {
}
}
func WithPullSpecOpts(pullSpec *env.PullSpec) MergeSpecOpt {
return func(ms *MergeSpec) {
ms.NoEdit = pullSpec.NoEdit
ms.NoCommit = pullSpec.NoCommit
ms.Force = pullSpec.Force
ms.NoFF = pullSpec.NoFF
ms.Squash = pullSpec.Squash
}
}
// NewMergeSpec returns a MergeSpec with the arguments provided.
func NewMergeSpec(
ctx context.Context,

View File

@@ -241,7 +241,7 @@ func performMerge(
return ws, "", noConflictsOrViolations, threeWayMerge, sql.ErrDatabaseNotFound.New(dbName)
}
ws, err = executeMerge(ctx, sess, dbName, spec.Squash, spec.HeadC, spec.MergeC, spec.MergeCSpecStr, ws, dbState.EditOpts(), spec.WorkingDiffs)
ws, err = executeMerge(ctx, sess, dbName, spec.Squash, spec.Force, spec.HeadC, spec.MergeC, spec.MergeCSpecStr, ws, dbState.EditOpts(), spec.WorkingDiffs)
if err == doltdb.ErrUnresolvedConflictsOrViolations {
// if there are unresolved conflicts, write the resulting working set back to the session and return an
// error message
@@ -265,7 +265,11 @@ func performMerge(
var commit string
if !noCommit {
author := fmt.Sprintf("%s <%s>", spec.Name, spec.Email)
commit, _, err = doDoltCommit(ctx, []string{"-m", msg, "--author", author})
args := []string{"-m", msg, "--author", author}
if spec.Force {
args = append(args, "--force")
}
commit, _, err = doDoltCommit(ctx, args)
if err != nil {
return ws, commit, noConflictsOrViolations, threeWayMerge, fmt.Errorf("dolt_commit failed")
}
@@ -316,6 +320,7 @@ func executeMerge(
sess *dsess.DoltSession,
dbName string,
squash bool,
force bool,
head, cm *doltdb.Commit,
cmSpec string,
ws *doltdb.WorkingSet,
@@ -333,7 +338,7 @@ func executeMerge(
return nil, err
}
}
return mergeRootToWorking(ctx, sess, dbName, squash, ws, result, workingDiffs, cm, cmSpec)
return mergeRootToWorking(ctx, sess, dbName, squash, force, ws, result, workingDiffs, cm, cmSpec)
}
func executeFFMerge(ctx *sql.Context, dbName string, squash bool, ws *doltdb.WorkingSet, dbData env.DbData, cm2 *doltdb.Commit, spec *merge.MergeSpec) (*doltdb.WorkingSet, error) {
@@ -399,7 +404,7 @@ func executeNoFFMerge(
}
result := &merge.Result{Root: mergeRoot, Stats: make(map[string]*merge.MergeStats)}
ws, err = mergeRootToWorking(ctx, dSess, dbName, false, ws, result, spec.WorkingDiffs, spec.MergeC, spec.MergeCSpecStr)
ws, err = mergeRootToWorking(ctx, dSess, dbName, false, spec.Force, ws, result, spec.WorkingDiffs, spec.MergeC, spec.MergeCSpecStr)
if err != nil {
// This error is recoverable, so we return a working set value along with the error
return ws, nil, err
@@ -515,7 +520,7 @@ func mergeRootToWorking(
ctx *sql.Context,
dSess *dsess.DoltSession,
dbName string,
squash bool,
squash, force bool,
ws *doltdb.WorkingSet,
merged *merge.Result,
workingDiffs map[string]hash.Hash,
@@ -538,7 +543,7 @@ func mergeRootToWorking(
}
ws = ws.WithWorkingRoot(working)
if !merged.HasMergeArtifacts() {
if !merged.HasMergeArtifacts() || !force {
ws = ws.WithStagedRoot(staged)
}
@@ -547,7 +552,7 @@ func mergeRootToWorking(
return nil, err
}
if merged.HasMergeArtifacts() {
if merged.HasMergeArtifacts() && !force {
// this error is recoverable in-session, so we return the new ws along with the error
return ws, doltdb.ErrUnresolvedConflictsOrViolations
}

View File

@@ -144,7 +144,6 @@ teardown() {
dolt checkout feature2
run dolt sql -q "show tables" -r csv
[ "$status" -eq 0 ]
echo "$output"
[ "${#lines[@]}" -eq 3 ]
[[ "$output" =~ "Table" ]] || false
[[ "$output" =~ "t1" ]] || false
@@ -152,33 +151,48 @@ teardown() {
}
@test "pull: pull force" {
skip "todo: support dolt pull --force"
cd repo2
dolt sql -q "create table t1 (a int)"
dolt commit -Am "2.0 commit"
dolt push -f origin main
cd repo1
dolt sql <<SQL
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE colors (
id INT NOT NULL,
color VARCHAR(32) NOT NULL,
PRIMARY KEY (id),
INDEX color_index(color)
);
CREATE TABLE objects (
id INT NOT NULL,
name VARCHAR(64) NOT NULL,
color VARCHAR(32)
);
SQL
dolt commit -A -m "Commit1"
dolt push origin main
cd ../repo2
dolt pull
dolt sql -q "alter table objects add constraint color FOREIGN KEY (color) REFERENCES colors(color)"
dolt commit -A -m "Commit2"
cd ../repo1
dolt sql -q "create table t2 (a int primary key)"
dolt sql -q "create table t3 (a int primary key)"
dolt commit -Am "2.1 commit"
dolt push -f origin main
dolt sql -q "INSERT INTO objects (id,name,color) VALUES (1,'truck','red'),(2,'ball','green'),(3,'shoe','blue')"
dolt commit -A -m "Commit3"
dolt push origin main
cd ../repo1
run dolt pull origin
cd ../repo2
run dolt pull
[ "$status" -eq 1 ]
[[ ! "$output" =~ "panic" ]] || false
[[ "$output" =~ "fetch failed; dataset head is not ancestor of commit" ]] || false
[[ "$output" =~ "CONSTRAINT VIOLATION" ]] || false
dolt pull -f origin
run dolt log -n 1
dolt merge --abort
run dolt pull -f
[ "$status" -eq 0 ]
[[ "$output" =~ "2.1 commit" ]] || false
run dolt sql -q "show tables" -r csv
[ "${#lines[@]}" -eq 4 ]
[[ "$output" =~ "t3" ]] || false
run dolt sql -q "select * from objects"
[ "$status" -eq 0 ]
[[ "$output" =~ "truck" ]] || false
[[ "$output" =~ "ball" ]] || false
[[ "$output" =~ "shoe" ]] || false
}
@test "pull: pull squash" {

View File

@@ -160,33 +160,47 @@ teardown() {
}
@test "sql-pull: dolt_pull force" {
skip "todo: support dolt pull --force (cli too)"
cd repo2
dolt sql -q "create table t2 (a int)"
dolt commit -am "2.0 commit"
cd repo1
dolt sql <<SQL
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE colors (
id INT NOT NULL,
color VARCHAR(32) NOT NULL,
PRIMARY KEY (id),
INDEX color_index(color)
);
CREATE TABLE objects (
id INT NOT NULL,
name VARCHAR(64) NOT NULL,
color VARCHAR(32)
);
SQL
dolt commit -A -m "Commit1"
dolt push origin main
cd ../repo2
dolt pull
dolt sql -q "alter table objects add constraint color FOREIGN KEY (color) REFERENCES colors(color)"
dolt commit -A -m "Commit2"
cd ../repo1
dolt sql -q "create table t2 (a int primary key)"
dolt sql -q "create table t3 (a int primary key)"
dolt commit -am "2.1 commit"
dolt push -f origin main
dolt sql -q "INSERT INTO objects (id,name,color) VALUES (1,'truck','red'),(2,'ball','green'),(3,'shoe','blue')"
dolt commit -A -m "Commit3"
dolt push origin main
cd ../repo2
run dolt sql -q "CALL dolt_pull('origin')"
run dolt sql -q "call dolt_pull()"
[ "$status" -eq 1 ]
[[ ! "$output" =~ "panic" ]] || false
[[ "$output" =~ "fetch failed; dataset head is not ancestor of commit" ]] || false
[[ "$output" =~ "Constraint violations" ]] || false
dolt sql -q "CALL dolt_pull('-f', 'origin')"
run dolt log -n 1
run dolt sql -q "call dolt_pull('-f')"
[ "$status" -eq 0 ]
[[ "$output" =~ "2.1 commit" ]] || false
run dolt sql -q "show tables" -r csv
[ "${#lines[@]}" -eq 4 ]
[[ "$output" =~ "t3" ]] || false
run dolt sql -q "select * from objects"
[ "$status" -eq 0 ]
[[ "$output" =~ "truck" ]] || false
[[ "$output" =~ "ball" ]] || false
[[ "$output" =~ "shoe" ]] || false
}
@test "sql-pull: CALL dolt_pull squash" {