mirror of
https://github.com/dolthub/dolt.git
synced 2026-03-17 23:56:33 -05:00
dolt merge --no-ff (#965)
This commit is contained in:
@@ -187,6 +187,49 @@ teardown() {
|
||||
[[ ! "$output" =~ "test1" ]] || false
|
||||
}
|
||||
|
||||
@test "no-ff merge" {
|
||||
dolt checkout -b merge_branch
|
||||
dolt SQL -q "INSERT INTO test1 values (0,1,2)"
|
||||
dolt add test1
|
||||
dolt commit -m "modify test1"
|
||||
|
||||
dolt checkout master
|
||||
run dolt merge merge_branch --no-ff -m "no-ff merge"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ ! "$output" =~ "Fast-forward" ]] || false
|
||||
|
||||
run dolt log
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "no-ff merge" ]] || false
|
||||
}
|
||||
|
||||
@test "no-ff merge doesn't stomp working changes and doesn't fast forward" {
|
||||
dolt checkout -b merge_branch
|
||||
dolt SQL -q "INSERT INTO test1 values (0,1,2)"
|
||||
dolt add test1
|
||||
dolt commit -m "modify test1"
|
||||
|
||||
dolt checkout master
|
||||
dolt SQL -q "INSERT INTO test2 values (0,1,2)"
|
||||
run dolt status
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test2" ]] || false
|
||||
[[ ! "$output" =~ "test1" ]] || false
|
||||
|
||||
run dolt merge merge_branch --no-ff -m "no-ff merge"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ ! "$output" =~ "Fast-forward" ]] || false
|
||||
|
||||
run dolt status
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "test2" ]] || false
|
||||
[[ ! "$output" =~ "test1" ]] || false
|
||||
|
||||
run dolt log
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" =~ "no-ff merge" ]] || false
|
||||
}
|
||||
|
||||
@test "3way merge rejected when working changes touch same tables" {
|
||||
dolt checkout -b merge_branch
|
||||
dolt SQL -q "INSERT INTO test1 values (0,1,2)"
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
const (
|
||||
abortParam = "abort"
|
||||
squashParam = "squash"
|
||||
noFFParam = "no-ff"
|
||||
)
|
||||
|
||||
var mergeDocs = cli.CommandDocumentationContent{
|
||||
@@ -50,6 +51,7 @@ The second syntax ({{.LessThan}}dolt merge --abort{{.GreaterThan}}) can only be
|
||||
|
||||
Synopsis: []string{
|
||||
"[--squash] {{.LessThan}}branch{{.GreaterThan}}",
|
||||
"--no-ff [-m message] {{.LessThan}}branch{{.GreaterThan}}",
|
||||
"--abort",
|
||||
},
|
||||
}
|
||||
@@ -81,6 +83,8 @@ func (cmd MergeCmd) createArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParser()
|
||||
ap.SupportsFlag(abortParam, "", abortDetails)
|
||||
ap.SupportsFlag(squashParam, "", "Merges changes to the working set without updating the commit history")
|
||||
ap.SupportsFlag(noFFParam, "", "Create a merge commit even when the merge resolves as a fast-forward.")
|
||||
ap.SupportsString(commitMessageArg, "m", "msg", "Use the given {{.LessThan}}msg{{.GreaterThan}} as the commit message.")
|
||||
return ap
|
||||
}
|
||||
|
||||
@@ -95,6 +99,11 @@ func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string,
|
||||
help, usage := cli.HelpAndUsagePrinters(cli.GetCommandDocumentation(commandStr, mergeDocs, ap))
|
||||
apr := cli.ParseArgs(ap, args, help)
|
||||
|
||||
if apr.ContainsAll(squashParam, noFFParam) {
|
||||
cli.PrintErrf("error: Flags '--%s' and '--%s' cannot be used together.\n", squashParam, noFFParam)
|
||||
return 1
|
||||
}
|
||||
|
||||
var verr errhand.VerboseError
|
||||
if apr.Contains(abortParam) {
|
||||
if !dEnv.IsMergeActive() {
|
||||
@@ -131,8 +140,7 @@ func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string,
|
||||
}
|
||||
|
||||
if verr == nil {
|
||||
squash := apr.Contains(squashParam)
|
||||
verr = mergeCommitSpec(ctx, squash, dEnv, commitSpecStr)
|
||||
verr = mergeCommitSpec(ctx, apr, dEnv, commitSpecStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,7 +162,7 @@ func abortMerge(ctx context.Context, doltEnv *env.DoltEnv) errhand.VerboseError
|
||||
return errhand.BuildDError("fatal: failed to revert changes").AddCause(err).Build()
|
||||
}
|
||||
|
||||
func mergeCommitSpec(ctx context.Context, squash bool, dEnv *env.DoltEnv, commitSpecStr string) errhand.VerboseError {
|
||||
func mergeCommitSpec(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv, commitSpecStr string) errhand.VerboseError {
|
||||
cm1, verr := ResolveCommitWithVErr(dEnv, "HEAD")
|
||||
|
||||
if verr != nil {
|
||||
@@ -186,6 +194,7 @@ func mergeCommitSpec(ctx context.Context, squash bool, dEnv *env.DoltEnv, commit
|
||||
|
||||
cli.Println("Updating", h1.String()+".."+h2.String())
|
||||
|
||||
squash := apr.Contains(squashParam)
|
||||
if squash {
|
||||
cli.Println("Squash commit -- not updating HEAD")
|
||||
}
|
||||
@@ -206,7 +215,11 @@ func mergeCommitSpec(ctx context.Context, squash bool, dEnv *env.DoltEnv, commit
|
||||
}
|
||||
|
||||
if ok, err := cm1.CanFastForwardTo(ctx, cm2); ok {
|
||||
return executeFFMerge(ctx, squash, dEnv, cm2, workingDiffs)
|
||||
if apr.Contains(noFFParam) {
|
||||
return execNoFFMerge(ctx, apr, dEnv, cm2, verr, workingDiffs)
|
||||
} else {
|
||||
return executeFFMerge(ctx, squash, dEnv, cm2, workingDiffs)
|
||||
}
|
||||
} else if err == doltdb.ErrUpToDate || err == doltdb.ErrIsAhead {
|
||||
cli.Println("Already up to date.")
|
||||
return nil
|
||||
@@ -215,6 +228,48 @@ func mergeCommitSpec(ctx context.Context, squash bool, dEnv *env.DoltEnv, commit
|
||||
}
|
||||
}
|
||||
|
||||
func execNoFFMerge(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv, cm2 *doltdb.Commit, verr errhand.VerboseError, workingDiffs map[string]hash.Hash) errhand.VerboseError {
|
||||
mergedRoot, err := cm2.GetRootValue()
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: reading from database").AddCause(err).Build()
|
||||
}
|
||||
|
||||
verr = mergedRootToWorking(ctx, false, dEnv, mergedRoot, workingDiffs, cm2, map[string]*merge.MergeStats{})
|
||||
|
||||
if verr != nil {
|
||||
return verr
|
||||
}
|
||||
|
||||
msg, msgOk := apr.GetValue(commitMessageArg)
|
||||
if !msgOk {
|
||||
msg = getCommitMessageFromEditor(ctx, dEnv)
|
||||
}
|
||||
|
||||
t := doltdb.CommitNowFunc()
|
||||
if commitTimeStr, ok := apr.GetValue(dateParam); ok {
|
||||
var err error
|
||||
t, err = parseDate(commitTimeStr)
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: invalid date").AddCause(err).Build()
|
||||
}
|
||||
}
|
||||
|
||||
err = actions.CommitStaged(ctx, dEnv, actions.CommitStagedProps{
|
||||
Message: msg,
|
||||
Date: t,
|
||||
AllowEmpty: apr.Contains(allowEmptyFlag),
|
||||
CheckForeignKeys: !apr.Contains(forceFlag),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errhand.BuildDError("error: committing").AddCause(err).Build()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyChanges(ctx context.Context, root *doltdb.RootValue, workingDiffs map[string]hash.Hash) (*doltdb.RootValue, errhand.VerboseError) {
|
||||
var err error
|
||||
for tblName, h := range workingDiffs {
|
||||
@@ -307,6 +362,12 @@ func executeMerge(ctx context.Context, squash bool, dEnv *env.DoltEnv, cm1, cm2
|
||||
}
|
||||
}
|
||||
|
||||
return mergedRootToWorking(ctx, squash, dEnv, mergedRoot, workingDiffs, cm2, tblToStats)
|
||||
}
|
||||
|
||||
func mergedRootToWorking(ctx context.Context, squash bool, dEnv *env.DoltEnv, mergedRoot *doltdb.RootValue, workingDiffs map[string]hash.Hash, cm2 *doltdb.Commit, tblToStats map[string]*merge.MergeStats) errhand.VerboseError {
|
||||
var err error
|
||||
|
||||
workingRoot := mergedRoot
|
||||
if len(workingDiffs) > 0 {
|
||||
workingRoot, err = applyChanges(ctx, mergedRoot, workingDiffs)
|
||||
|
||||
@@ -104,8 +104,7 @@ func pullFromRemote(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgPa
|
||||
remoteTrackRef := refSpec.DestRef(branch)
|
||||
|
||||
if remoteTrackRef != nil {
|
||||
squash := apr.Contains(squashParam)
|
||||
verr = pullRemoteBranch(ctx, squash, dEnv, remote, branch, remoteTrackRef)
|
||||
verr = pullRemoteBranch(ctx, apr, dEnv, remote, branch, remoteTrackRef)
|
||||
|
||||
if verr != nil {
|
||||
return verr
|
||||
@@ -128,7 +127,7 @@ func pullFromRemote(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgPa
|
||||
return nil
|
||||
}
|
||||
|
||||
func pullRemoteBranch(ctx context.Context, squash bool, dEnv *env.DoltEnv, r env.Remote, srcRef, destRef ref.DoltRef) errhand.VerboseError {
|
||||
func pullRemoteBranch(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv, r env.Remote, srcRef, destRef ref.DoltRef) errhand.VerboseError {
|
||||
srcDB, err := r.GetRemoteDB(ctx, dEnv.DoltDB.ValueReadWriter().Format())
|
||||
|
||||
if err != nil {
|
||||
@@ -147,5 +146,5 @@ func pullRemoteBranch(ctx context.Context, squash bool, dEnv *env.DoltEnv, r env
|
||||
return errhand.BuildDError("error: fetch failed").AddCause(err).Build()
|
||||
}
|
||||
|
||||
return mergeCommitSpec(ctx, squash, dEnv, destRef.String())
|
||||
return mergeCommitSpec(ctx, apr, dEnv, destRef.String())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user