github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/dprocedures/dolt_clone.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 "path" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 22 "github.com/dolthub/dolt/go/cmd/dolt/cli" 23 "github.com/dolthub/dolt/go/cmd/dolt/errhand" 24 "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" 25 "github.com/dolthub/dolt/go/libraries/doltcore/env" 26 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" 27 "github.com/dolthub/dolt/go/libraries/utils/argparser" 28 "github.com/dolthub/dolt/go/libraries/utils/config" 29 "github.com/dolthub/dolt/go/libraries/utils/earl" 30 ) 31 32 // doltClone is the stored procedure version for the CLI command `dolt clone`. 33 func doltClone(ctx *sql.Context, args ...string) (sql.RowIter, error) { 34 ap := cli.CreateCloneArgParser() 35 apr, err := ap.Parse(args) 36 if err != nil { 37 return nil, err 38 } 39 40 remoteName := apr.GetValueOrDefault(cli.RemoteParam, "origin") 41 branch := apr.GetValueOrDefault(cli.BranchParam, "") 42 dir, urlStr, err := getDirectoryAndUrlString(apr) 43 if err != nil { 44 return nil, err 45 } 46 47 sess := dsess.DSessFromSess(ctx.Session) 48 _, remoteUrl, err := env.GetAbsRemoteUrl(sess.Provider().FileSystem(), emptyConfig(), urlStr) 49 if err != nil { 50 return nil, errhand.BuildDError("error: '%s' is not valid.", urlStr).Build() 51 } 52 53 // There are several remote params (AWS/GCP/OCI paths, creds, etc) which are pulled from the global server using 54 // server config, environment vars and such. The --user flag is the only one that we can override with a command flag. 55 remoteParms := map[string]string{} 56 if user, hasUser := apr.GetValue(cli.UserFlag); hasUser { 57 remoteParms[dbfactory.GRPCUsernameAuthParam] = user 58 } 59 60 depth, ok := apr.GetInt(cli.DepthFlag) 61 if !ok { 62 depth = -1 63 } 64 65 err = sess.Provider().CloneDatabaseFromRemote(ctx, dir, branch, remoteName, remoteUrl, depth, remoteParms) 66 if err != nil { 67 return nil, err 68 } 69 70 return rowToIter(int64(0)), nil 71 } 72 73 func emptyConfig() config.ReadableConfig { 74 return &config.MapConfig{} 75 } 76 77 func getDirectoryAndUrlString(apr *argparser.ArgParseResults) (string, string, error) { 78 if apr.NArg() < 1 || apr.NArg() > 2 { 79 return "", "", errhand.BuildDError("error: invalid number of arguments: database URL must be specified and database name is optional").Build() 80 } 81 82 urlStr := apr.Arg(0) 83 _, err := earl.Parse(urlStr) 84 if err != nil { 85 return "", "", errhand.BuildDError("error: invalid remote url: " + urlStr).Build() 86 } 87 88 var dir string 89 if apr.NArg() == 2 { 90 dir = apr.Arg(1) 91 } else { 92 dir = path.Base(urlStr) 93 if dir == "." { 94 dir = path.Dir(urlStr) 95 } else if dir == "/" { 96 return "", "", errhand.BuildDError("Could not infer repo name. Please explicitly define a directory for this url").Build() 97 } 98 } 99 100 return dir, urlStr, nil 101 }