Skip to content

Commit 0aa83d2

Browse files
committed
fix consecutive remotesapi pushes failing due to working set not being updated on fast-forward
1 parent 1543cc5 commit 0aa83d2

File tree

7 files changed

+25
-30
lines changed

7 files changed

+25
-30
lines changed

go/libraries/doltcore/doltdb/doltdb.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -885,10 +885,12 @@ func (ddb *DoltDB) Commit(ctx context.Context, valHash hash.Hash, dref ref.DoltR
885885
return ddb.CommitWithParentSpecs(ctx, valHash, dref, nil, cm)
886886
}
887887

888-
// FastForwardWithWorkspaceCheck will perform a fast forward update of the branch given to the commit given, but only
889-
// if the working set is in sync with the head of the branch given. This is used in the course of pushing to a remote.
890-
// If the target doesn't currently have the working set ref, then no working set change will be made.
891-
func (ddb *DoltDB) FastForwardWithWorkspaceCheck(ctx context.Context, branch ref.DoltRef, commit *Commit) error {
888+
// FastForwardWithWorkspaceCheck performs a fast-forward of |branch| to |commit| only if the remote
889+
// working set is in sync with its HEAD, then updates the working set to match the new HEAD.
890+
// This is used when pushing to a remote. If the remote does not maintain a working set, no working
891+
// set update is performed.
892+
// When |allowDirtyWorking| is true, the working set may have unstaged changes, such as ignored tables.
893+
func (ddb *DoltDB) FastForwardWithWorkspaceCheck(ctx context.Context, branch ref.DoltRef, commit *Commit, allowDirtyWorking bool) error {
892894
ds, err := ddb.db.GetDataset(ctx, branch.String())
893895
if err != nil {
894896
return err
@@ -909,7 +911,7 @@ func (ddb *DoltDB) FastForwardWithWorkspaceCheck(ctx context.Context, branch ref
909911
ws = wsRef.String()
910912
}
911913

912-
_, err = ddb.db.FastForward(ctx, ds, addr, ws)
914+
_, err = ddb.db.FastForward(ctx, ds, addr, ws, allowDirtyWorking)
913915

914916
return err
915917
}
@@ -931,7 +933,7 @@ func (ddb *DoltDB) FastForwardToHash(ctx context.Context, branch ref.DoltRef, ha
931933
return err
932934
}
933935

934-
_, err = ddb.db.FastForward(ctx, ds, hash, "")
936+
_, err = ddb.db.FastForward(ctx, ds, hash, "", false)
935937

936938
return err
937939
}

go/libraries/doltcore/doltdb/hooksdatabase.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ func (db hooksDatabase) SetHead(ctx context.Context, ds datas.Dataset, newHeadAd
164164
return ds, err
165165
}
166166

167-
func (db hooksDatabase) FastForward(ctx context.Context, ds datas.Dataset, newHeadAddr hash.Hash, workingSetPath string) (datas.Dataset, error) {
168-
ds, err := db.Database.FastForward(ctx, ds, newHeadAddr, workingSetPath)
167+
func (db hooksDatabase) FastForward(ctx context.Context, ds datas.Dataset, newHeadAddr hash.Hash, workingSetPath string, allowDirtyWorking bool) (datas.Dataset, error) {
168+
ds, err := db.Database.FastForward(ctx, ds, newHeadAddr, workingSetPath, allowDirtyWorking)
169169
if err == nil {
170170
db.ExecuteCommitHooks(ctx, ds, false, false)
171171
}

go/libraries/doltcore/env/actions/remotes.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,13 @@ func Push(ctx context.Context, tempTableDir string, mode ref.UpdateMode, destRef
8686
}
8787
err = srcDB.SetHeadToCommit(ctx, remoteRef, commit)
8888
case ref.FastForwardOnly:
89-
// ResolveBranchRoots fails for remotes that don't maintain a working set (e.g. file://),
90-
// in which case FastForwardWithWorkspaceCheck handles it correctly without the ignored-table check.
89+
// Ignored tables create a staged/working mismatch that blocks fast-forward pushes, so we detect and permit that case.
9190
onlyIgnored := false
9291
roots, err := destDB.ResolveBranchRoots(ctx, destRef)
9392
if err == nil {
9493
onlyIgnored, _ = diff.WorkingSetContainsOnlyIgnoredTables(ctx, roots)
9594
}
96-
if onlyIgnored {
97-
err = destDB.FastForward(ctx, destRef, commit)
98-
} else {
99-
err = destDB.FastForwardWithWorkspaceCheck(ctx, destRef, commit)
100-
}
95+
err = destDB.FastForwardWithWorkspaceCheck(ctx, destRef, commit, onlyIgnored)
10196
if err != nil {
10297
return err
10398
}

go/store/datas/database.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,12 @@ type Database interface {
149149
// is not provided, no working set update will be performed.
150150
SetHead(ctx context.Context, ds Dataset, newHeadAddr hash.Hash, workingSetPath string) (Dataset, error)
151151

152-
// FastForward takes a types.Ref to a Commit object and makes it the new
153-
// Head of ds iff it is a descendant of the current Head. Intended to be
154-
// used e.g. after a call to Pull(). If the update cannot be performed,
155-
// e.g., because another process moved the current Head out from under
156-
// you, err will be non-nil.
157-
// The workingSetPath is the path to the working set that should be used for updating the working set. If one
158-
// is not provided, no working set update will be performed.
159-
FastForward(ctx context.Context, ds Dataset, newHeadAddr hash.Hash, workingSetPath string) (Dataset, error)
152+
// FastForward sets the head of |ds| to the commit at |newHeadAddr| if it is a descendant of
153+
// the current head. If the update cannot be performed, for example because another writer has
154+
// moved the head concurrently, err will be non-nil.
155+
// If |workingSetPath| is non-empty, the working set at that path is updated to match the new head.
156+
// When |allowDirtyWorking| is true, the working set may have unstaged changes, such as ignored tables.
157+
FastForward(ctx context.Context, ds Dataset, newHeadAddr hash.Hash, workingSetPath string, allowDirtyWorking bool) (Dataset, error)
160158

161159
// Stats may return some kind of struct that reports statistics about the
162160
// ChunkStore that backs this Database instance. The type is

go/store/datas/database_common.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,13 @@ func (db *database) doSetHead(ctx context.Context, ds Dataset, addr hash.Hash, w
337337
})
338338
}
339339

340-
func (db *database) FastForward(ctx context.Context, ds Dataset, newHeadAddr hash.Hash, wsPath string) (Dataset, error) {
340+
func (db *database) FastForward(ctx context.Context, ds Dataset, newHeadAddr hash.Hash, wsPath string, allowDirtyWorking bool) (Dataset, error) {
341341
return db.doHeadUpdate(ctx, ds, func(ds Dataset) error {
342-
return db.doFastForward(ctx, ds, newHeadAddr, wsPath)
342+
return db.doFastForward(ctx, ds, newHeadAddr, wsPath, allowDirtyWorking)
343343
})
344344
}
345345

346-
func (db *database) doFastForward(ctx context.Context, ds Dataset, newHeadAddr hash.Hash, workingSetPath string) error {
346+
func (db *database) doFastForward(ctx context.Context, ds Dataset, newHeadAddr hash.Hash, workingSetPath string, allowDirtyWorking bool) error {
347347
newHead, err := db.readHead(ctx, newHeadAddr)
348348
if err != nil {
349349
return err
@@ -434,7 +434,7 @@ func (db *database) doFastForward(ctx context.Context, ds Dataset, newHeadAddr h
434434

435435
stagedHash := hash.New(msg.StagedRootAddrBytes())
436436
workingSetHash := hash.New(msg.WorkingRootAddrBytes())
437-
if stagedHash != workingSetHash {
437+
if !allowDirtyWorking && stagedHash != workingSetHash {
438438
return prolly.AddressMap{}, ErrDirtyWorkspace
439439
}
440440

go/store/datas/database_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ func (suite *DatabaseSuite) TestFastForward() {
442442
cCommitAddr := mustHeadAddr(ds) // To use in FastForward() below.
443443

444444
// FastForward should disallow this, as |a| is not a descendant of |c|
445-
_, err = suite.db.FastForward(context.Background(), ds, aCommitAddr, "")
445+
_, err = suite.db.FastForward(context.Background(), ds, aCommitAddr, "", false)
446446
suite.Error(err)
447447

448448
// Move Head back to something earlier in the lineage, so we can test FastForward
@@ -451,7 +451,7 @@ func (suite *DatabaseSuite) TestFastForward() {
451451
suite.True(mustHeadValue(ds).Equals(a))
452452

453453
// This should succeed, because while |a| is not a direct parent of |c|, it is an ancestor.
454-
ds, err = suite.db.FastForward(context.Background(), ds, cCommitAddr, "")
454+
ds, err = suite.db.FastForward(context.Background(), ds, cCommitAddr, "", false)
455455
suite.Require().NoError(err)
456456
suite.True(mustHeadValue(ds).Equals(c))
457457
}

go/store/datas/pull/puller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ func testPuller(t *testing.T, makeDB datasFactory) {
412412

413413
sinkDS, err := sinkdb.GetDataset(ctx, "ds")
414414
require.NoError(t, err)
415-
sinkDS, err = sinkdb.FastForward(ctx, sinkDS, rootAddr, "")
415+
sinkDS, err = sinkdb.FastForward(ctx, sinkDS, rootAddr, "", false)
416416
require.NoError(t, err)
417417

418418
require.NoError(t, err)

0 commit comments

Comments
 (0)