github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/dprocedures/dolt_push.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package dprocedures 16 17 import ( 18 "fmt" 19 "strconv" 20 21 "github.com/dolthub/go-mysql-server/sql" 22 "github.com/dolthub/go-mysql-server/sql/types" 23 24 "github.com/dolthub/dolt/go/cmd/dolt/cli" 25 "github.com/dolthub/dolt/go/libraries/doltcore/branch_control" 26 "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" 27 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 28 "github.com/dolthub/dolt/go/libraries/doltcore/env" 29 "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" 30 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" 31 "github.com/dolthub/dolt/go/libraries/utils/config" 32 "github.com/dolthub/dolt/go/store/datas" 33 ) 34 35 var doltPushSchema = []*sql.Column{ 36 { 37 Name: "status", 38 Type: types.Int64, 39 Nullable: false, 40 }, 41 { 42 Name: "message", 43 Type: types.LongText, 44 Nullable: true, 45 }, 46 } 47 48 // doltPush is the stored procedure version for the CLI command `dolt push`. 49 func doltPush(ctx *sql.Context, args ...string) (sql.RowIter, error) { 50 res, message, err := doDoltPush(ctx, args) 51 return rowToIter(int64(res), message), err 52 } 53 54 func doDoltPush(ctx *sql.Context, args []string) (int, string, error) { 55 dbName := ctx.GetCurrentDatabase() 56 57 if len(dbName) == 0 { 58 return cmdFailure, "", fmt.Errorf("empty database name") 59 } 60 if err := branch_control.CheckAccess(ctx, branch_control.Permissions_Write); err != nil { 61 return cmdFailure, "", err 62 } 63 64 sess := dsess.DSessFromSess(ctx.Session) 65 dbData, ok := sess.GetDbData(ctx, dbName) 66 if !ok { 67 return cmdFailure, "", fmt.Errorf("could not load database %s", dbName) 68 } 69 70 apr, err := cli.CreatePushArgParser().Parse(args) 71 if err != nil { 72 return cmdFailure, "", err 73 } 74 75 autoSetUpRemote := loadConfig(ctx).GetStringOrDefault(config.PushAutoSetupRemote, "false") 76 pushAutoSetUpRemote, err := strconv.ParseBool(autoSetUpRemote) 77 if err != nil { 78 return cmdFailure, "", err 79 } 80 81 targets, remote, err := env.NewPushOpts(ctx, apr, dbData.Rsr, dbData.Ddb, apr.Contains(cli.ForceFlag), apr.Contains(cli.SetUpstreamFlag), pushAutoSetUpRemote, apr.Contains(cli.AllFlag)) 82 if err != nil { 83 return cmdFailure, "", err 84 } 85 86 if user, hasUser := apr.GetValue(cli.UserFlag); hasUser { 87 rmt := (*remote).WithParams(map[string]string{ 88 dbfactory.GRPCUsernameAuthParam: user, 89 }) 90 remote = &rmt 91 } 92 93 remoteDB, err := sess.Provider().GetRemoteDB(ctx, dbData.Ddb.ValueReadWriter().Format(), *remote, true) 94 if err != nil { 95 return cmdFailure, "", actions.HandleInitRemoteStorageClientErr(remote.Name, remote.Url, err) 96 } 97 98 tmpDir, err := dbData.Rsw.TempTableFilesDir() 99 if err != nil { 100 return cmdFailure, "", err 101 } 102 103 var returnMsg string 104 po := &env.PushOptions{ 105 Targets: targets, 106 Remote: remote, 107 Rsr: dbData.Rsr, 108 Rsw: dbData.Rsw, 109 SrcDb: dbData.Ddb, 110 DestDb: remoteDB, 111 TmpDir: tmpDir, 112 } 113 returnMsg, err = actions.DoPush(ctx, po, runProgFuncs, stopProgFuncs) 114 if err != nil { 115 switch err { 116 case doltdb.ErrUpToDate: 117 return cmdSuccess, "Everything up-to-date", nil 118 case datas.ErrMergeNeeded: 119 return cmdFailure, returnMsg, fmt.Errorf("%w; the tip of your current branch is behind its remote counterpart", err) 120 default: 121 if returnMsg != "" { 122 // For multiple branches push, we need to print successful push message 123 // before the error message. We currently cannot return success message 124 // if there was a failed push with error. So, we need to include the success 125 // message in the error message before returning. 126 err = fmt.Errorf("%s\n%s", returnMsg, err.Error()) 127 } 128 return cmdFailure, "", err 129 } 130 } 131 // TODO : set upstream should be persisted outside of session 132 return cmdSuccess, returnMsg, nil 133 }