From eef66f7fa518f21f7af24a8d820326de77aabe14 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Wed, 29 Nov 2023 14:40:09 -0800 Subject: [PATCH 01/63] New propto fields --- go/libraries/events/emitter.go | 4 +++- proto/dolt/services/eventsapi/v1alpha1/event_constants.proto | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 53b9bbcc12..cce62c2526 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -30,6 +30,8 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/iohelp" ) +var Application = eventsapi.AppID_APP_DOLT + // Emitter is an interface used for processing a batch of events type Emitter interface { // LogEvents takes a batch of events and processes them @@ -110,7 +112,7 @@ func (em *GrpcEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) Version: version, Platform: plat, Events: evts, - App: eventsapi.AppID_APP_DOLT, + App: Application, } _, err := em.client.LogEvents(ctx, &req) diff --git a/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto b/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto index 51e6db7703..7138d083fb 100644 --- a/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto +++ b/proto/dolt/services/eventsapi/v1alpha1/event_constants.proto @@ -92,6 +92,7 @@ enum ClientEventType { STASH_POP = 60; SHOW = 61; PROFILE = 62; + SQL_SERVER_HEARTBEAT = 63; } enum MetricID { @@ -110,4 +111,5 @@ enum AttributeID { enum AppID { APP_ID_UNSPECIFIED = 0; APP_DOLT = 1; + APP_DOLTGRES = 2; } From b0a97412d9cee7a91d01e70c3204537bcd6298ff Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Wed, 29 Nov 2023 14:41:23 -0800 Subject: [PATCH 02/63] Cleaner emit logic --- go/cmd/dolt/dolt.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 41b3ef5b28..30f9d41077 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -473,28 +473,19 @@ func runMain() int { emitter := events.NewFileEmitter(root, dbfactory.DoltDir) defer func() { - ces := events.GlobalCollector.Close() - // events.WriterEmitter{cli.CliOut}.LogEvents(Version, ces) - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") - disabled, err := strconv.ParseBool(metricsDisabled) - if err != nil { - // log.Print(err) + if err != nil || disabled { return } - if disabled { - return - } + ces := events.GlobalCollector.Close() // write events _ = emitter.LogEvents(Version, ces) // flush events - if err := processEventsDir(args, dEnv); err != nil { - // log.Print(err) - } + _ = processEventsDir(args, dEnv) }() if needsWriteAccess(subcommandName) { From 9d70fe7bf5a0120f076fa6c49bd3f5d205295e8b Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 14:37:33 -0800 Subject: [PATCH 03/63] Stop invoking a separate process to flush events --- go/cmd/dolt/commands/send_metrics.go | 39 ++++++++++++++-------------- go/cmd/dolt/dolt.go | 34 ++++++++++++------------ 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 3afbf0ffe7..6b7b6c988d 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -21,6 +21,7 @@ import ( "strconv" "time" + "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/fatih/color" "google.golang.org/grpc" @@ -82,7 +83,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st ap := cmd.ArgParser() - help, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{ShortDesc: sendMetricsShortDesc}, ap)) + help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{ShortDesc: sendMetricsShortDesc}, ap)) apr := cli.ParseArgsOrDie(ap, args, help) metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") @@ -102,25 +103,13 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() - root, err := dEnv.GetUserHomeDir() + userHomeDir, err := dEnv.GetUserHomeDir() if err != nil { - // log.Print(err) - return 1 + return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - dolt := dbfactory.DoltDir - - var flusher events.Flusher - - if apr.Contains(outputFlag) { - flusher = events.NewIOFlusher(dEnv.FS, root, dolt) - } else { - grpcEmitter := getGRPCEmitter(dEnv) - - flusher = events.NewGrpcEventFlusher(dEnv.FS, root, dolt, grpcEmitter) - } - - err = flusher.Flush(ctx) + outputToStdio := apr.Contains(outputFlag) + err = FlushEvents(ctx, dEnv, userHomeDir, outputToStdio) if err != nil { if err == events.ErrFileLocked { @@ -136,8 +125,20 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return 1 } -// getGRPCEmitter gets the connection to the events grpc service -func getGRPCEmitter(dEnv *env.DoltEnv) *events.GrpcEmitter { +func FlushEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { + var flusher events.Flusher + if outputToStdio { + flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) + } else { + grpcEmitter := GRPCEventEmitterForEnv(dEnv) + flusher = events.NewGrpcEventFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, grpcEmitter) + } + + return flusher.Flush(ctx) +} + +// GRPCEventEmitterForEnv returns an event emitter for the given environment +func GRPCEventEmitterForEnv(dEnv *env.DoltEnv) *events.GrpcEmitter { host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 1901482635..2c1af5427e 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -480,7 +480,7 @@ func runMain() int { _ = emitter.LogEvents(Version, ces) // flush events - _ = processEventsDir(args, dEnv) + _ = processEventsDir(ctx, args, dEnv) }() if needsWriteAccess(subcommandName) { @@ -752,33 +752,35 @@ func seedGlobalRand() { } // processEventsDir runs the dolt send-metrics command in a new process -func processEventsDir(args []string, dEnv *env.DoltEnv) error { +func processEventsDir(ctx context.Context, args []string, dEnv *env.DoltEnv) error { if len(args) > 0 { - ignoreCommands := map[string]struct{}{ - commands.SendMetricsCommand: {}, - "init": {}, - "config": {}, - } - - _, ok := ignoreCommands[args[0]] - - if ok { + if !shouldFlushEvents(args[0]) { return nil } - - cmd := exec.Command("dolt", commands.SendMetricsCommand) - - if err := cmd.Start(); err != nil { - // log.Print(err) + + userHomeDir, err := dEnv.GetUserHomeDir() + if err != nil { return err } + // TODO: handle stdio output + _ = commands.FlushEvents(ctx, dEnv, userHomeDir, false) return nil } return nil } +func shouldFlushEvents(command string) bool { + ignoreCommands := map[string]struct{}{ + commands.SendMetricsCommand: {}, + "init": {}, + "config": {}, + } + _, ok := ignoreCommands[command] + return !ok +} + func interceptSendMetrics(ctx context.Context, args []string) (bool, int) { if len(args) < 1 || args[0] != commands.SendMetricsCommand { return false, 0 From e07983262a8c6d21d04ba5eae916aaee81ee9e5c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 14:55:52 -0800 Subject: [PATCH 04/63] Small cleanup --- go/cmd/dolt/commands/send_metrics.go | 5 +++-- go/cmd/dolt/dolt.go | 30 ++++++++++------------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 6b7b6c988d..1ca5107c8c 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -109,7 +109,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st } outputToStdio := apr.Contains(outputFlag) - err = FlushEvents(ctx, dEnv, userHomeDir, outputToStdio) + err = FlushLoggedEvents(ctx, dEnv, userHomeDir, outputToStdio) if err != nil { if err == events.ErrFileLocked { @@ -125,7 +125,8 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return 1 } -func FlushEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { +// FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter +func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { var flusher events.Flusher if outputToStdio { flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 2c1af5427e..fa9067f478 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -23,7 +23,6 @@ import ( "net/http" _ "net/http/pprof" "os" - "os/exec" "strconv" "time" @@ -437,7 +436,7 @@ func runMain() int { fs = filesys.LocalFS dEnv := env.Load(ctx, env.GetCurrentUserHomeDir, fs, doltdb.LocalDirDoltDB, Version) - root, err := env.GetCurrentUserHomeDir() + homeDir, err := env.GetCurrentUserHomeDir() if err != nil { cli.PrintErrln(color.RedString("Failed to load the HOME directory: %v", err)) return 1 @@ -464,9 +463,7 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - - emitter := events.NewFileEmitter(root, dbfactory.DoltDir) - + defer func() { metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) @@ -474,13 +471,14 @@ func runMain() int { return } - ces := events.GlobalCollector.Close() - // write events - _ = emitter.LogEvents(Version, ces) + emitter := events.NewFileEmitter(homeDir, dbfactory.DoltDir) + _ = emitter.LogEvents(Version, events.GlobalCollector.Close()) // flush events - _ = processEventsDir(ctx, args, dEnv) + if len(args) > 0 && shouldFlushEvents(args[0]) { + _ = processEventsDir(ctx, dEnv) + } }() if needsWriteAccess(subcommandName) { @@ -751,24 +749,16 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir runs the dolt send-metrics command in a new process -func processEventsDir(ctx context.Context, args []string, dEnv *env.DoltEnv) error { - if len(args) > 0 { - if !shouldFlushEvents(args[0]) { - return nil - } - +// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). +func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { userHomeDir, err := dEnv.GetUserHomeDir() if err != nil { return err } // TODO: handle stdio output - _ = commands.FlushEvents(ctx, dEnv, userHomeDir, false) + _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) return nil - } - - return nil } func shouldFlushEvents(command string) bool { From 47f34b2b1feae4d6fe29ff02c227b8b7e7bb72aa Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 15:05:07 -0800 Subject: [PATCH 05/63] Removed hard-coded dolt ref --- go/libraries/events/file_backed_proc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/events/file_backed_proc.go b/go/libraries/events/file_backed_proc.go index a75ae2df7d..2f4164b2ae 100644 --- a/go/libraries/events/file_backed_proc.go +++ b/go/libraries/events/file_backed_proc.go @@ -210,7 +210,7 @@ func (fbp *FileBackedProc) WriteEvents(version string, evts []*eventsapi.ClientE Version: version, Platform: plat, Events: evts, - App: eventsapi.AppID_APP_DOLT, + App: Application, } data, err := proto.Marshal(req) From be31b2852e2b8c62acd1ecce99a16fc5843bdd17 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Fri, 1 Dec 2023 15:28:56 -0800 Subject: [PATCH 06/63] adds --single-branch for dolt clone --- go/cmd/dolt/cli/arg_parser_helpers.go | 1 + go/cmd/dolt/cli/flags.go | 1 + go/cmd/dolt/commands/clone.go | 3 +- go/libraries/doltcore/env/actions/clone.go | 30 +++++++++---------- .../doltcore/sqle/database_provider.go | 2 +- integration-tests/bats/remotes.bats | 15 ++++++++++ 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/go/cmd/dolt/cli/arg_parser_helpers.go b/go/cmd/dolt/cli/arg_parser_helpers.go index 9848beb391..eb8cd1ae06 100644 --- a/go/cmd/dolt/cli/arg_parser_helpers.go +++ b/go/cmd/dolt/cli/arg_parser_helpers.go @@ -125,6 +125,7 @@ func CreateCloneArgParser() *argparser.ArgParser { ap.SupportsString(dbfactory.OSSCredsFileParam, "", "file", "OSS credentials file.") ap.SupportsString(dbfactory.OSSCredsProfile, "", "profile", "OSS profile to use.") ap.SupportsString(UserFlag, "u", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.") + ap.SupportsFlag(SingleBranchFlag, "", "Clone only the history leading to the tip of a single branch, either specified by --branch or the primary branch remote's HEAD points at.") return ap } diff --git a/go/cmd/dolt/cli/flags.go b/go/cmd/dolt/cli/flags.go index 0a411ddc03..1fdaa1b013 100644 --- a/go/cmd/dolt/cli/flags.go +++ b/go/cmd/dolt/cli/flags.go @@ -59,6 +59,7 @@ const ( ShallowFlag = "shallow" ShowIgnoredFlag = "ignored" SilentFlag = "silent" + SingleBranchFlag = "single-branch" SkipEmptyFlag = "skip-empty" SoftResetParam = "soft" SquashParam = "squash" diff --git a/go/cmd/dolt/commands/clone.go b/go/cmd/dolt/commands/clone.go index 5768563401..2940f2fa48 100644 --- a/go/cmd/dolt/commands/clone.go +++ b/go/cmd/dolt/commands/clone.go @@ -98,6 +98,7 @@ func (cmd CloneCmd) Exec(ctx context.Context, commandStr string, args []string, func clone(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv) errhand.VerboseError { remoteName := apr.GetValueOrDefault(cli.RemoteParam, "origin") branch := apr.GetValueOrDefault(cli.BranchParam, "") + singleBranch := apr.Contains(cli.SingleBranchFlag) dir, urlStr, verr := parseArgs(apr) if verr != nil { return verr @@ -143,7 +144,7 @@ func clone(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEn // Nil out the old Dolt env so we don't accidentally operate on the wrong database dEnv = nil - err = actions.CloneRemote(ctx, srcDB, remoteName, branch, clonedEnv) + err = actions.CloneRemote(ctx, srcDB, remoteName, branch, singleBranch, clonedEnv) if err != nil { // If we're cloning into a directory that already exists do not erase it. Otherwise // make best effort to delete the directory we created. diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index f24abd5142..82d5de273a 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -156,7 +156,7 @@ func sortedKeys(m map[string]iohelp.ReadStats) []string { return keys } -func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch string, dEnv *env.DoltEnv) error { +func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch string, singleBranch bool, dEnv *env.DoltEnv) error { eventCh := make(chan pull.TableFileEvent, 128) wg := &sync.WaitGroup{} @@ -215,25 +215,25 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // create remote refs corresponding to each of them. We delete all of // the local branches except for the one corresponding to |branch|. for _, brnch := range branches { - cs, _ := doltdb.NewCommitSpec(brnch.GetPath()) - cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) - if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, brnch.String(), err.Error()) - - } - - remoteRef := ref.NewRemoteRef(remoteName, brnch.GetPath()) - err = dEnv.DoltDB.SetHeadToCommit(ctx, remoteRef, cm) - if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToCreateRemoteRef, remoteRef.String(), err.Error()) - - } - if brnch.GetPath() != branch { err := dEnv.DoltDB.DeleteBranch(ctx, brnch, nil) if err != nil { return fmt.Errorf("%w: %s; %s", ErrFailedToDeleteBranch, brnch.String(), err.Error()) } + } else if !singleBranch || brnch.GetPath() == branch { + cs, _ := doltdb.NewCommitSpec(brnch.GetPath()) + cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) + if err != nil { + return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, brnch.String(), err.Error()) + + } + + remoteRef := ref.NewRemoteRef(remoteName, brnch.GetPath()) + err = dEnv.DoltDB.SetHeadToCommit(ctx, remoteRef, cm) + if err != nil { + return fmt.Errorf("%w: %s; %s", ErrFailedToCreateRemoteRef, remoteRef.String(), err.Error()) + + } } } diff --git a/go/libraries/doltcore/sqle/database_provider.go b/go/libraries/doltcore/sqle/database_provider.go index 4113578600..5ff4c1af57 100644 --- a/go/libraries/doltcore/sqle/database_provider.go +++ b/go/libraries/doltcore/sqle/database_provider.go @@ -527,7 +527,7 @@ func (p *DoltDatabaseProvider) cloneDatabaseFromRemote( return nil, err } - err = actions.CloneRemote(ctx, srcDB, remoteName, branch, dEnv) + err = actions.CloneRemote(ctx, srcDB, remoteName, branch, false, dEnv) if err != nil { return nil, err } diff --git a/integration-tests/bats/remotes.bats b/integration-tests/bats/remotes.bats index 76698efc6d..0dd65d7d5e 100644 --- a/integration-tests/bats/remotes.bats +++ b/integration-tests/bats/remotes.bats @@ -1008,6 +1008,21 @@ create_five_remote_branches_main_and_master() { [[ "$output" =~ "remotes/origin/branch-two" ]] || false } +@test "remotes: clone --single-branch does not create remote refs for all remote branches" { + create_three_remote_branches + cd dolt-repo-clones + dolt clone --single-branch http://localhost:50051/test-org/test-repo + cd test-repo + run dolt branch -a + [ "$status" -eq 0 ] + [[ "$output" =~ "* main" ]] || false + [[ ! "$output" =~ " branch-one" ]] || false + [[ ! "$output" =~ " branch-two" ]] || false + [[ "$output" =~ "remotes/origin/main" ]] || false + [[ ! "$output" =~ "remotes/origin/branch-one" ]] || false + [[ ! "$output" =~ "remotes/origin/branch-two" ]] || false +} + @test "remotes: fetch creates new remote refs for new remote branches" { create_main_remote_branch From 90b62c8bd75a5c1cc05e2d9d0c4a44caf0912345 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Fri, 1 Dec 2023 15:51:44 -0800 Subject: [PATCH 07/63] small fix --- go/libraries/doltcore/dtestutils/testcommands/multienv.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/doltcore/dtestutils/testcommands/multienv.go b/go/libraries/doltcore/dtestutils/testcommands/multienv.go index ecb6ba4db1..f5ac33a219 100644 --- a/go/libraries/doltcore/dtestutils/testcommands/multienv.go +++ b/go/libraries/doltcore/dtestutils/testcommands/multienv.go @@ -195,7 +195,7 @@ func (mr *MultiRepoTestSetup) CloneDB(fromRemote, dbName string) { mr.Errhand(err) } - err = actions.CloneRemote(ctx, srcDB, r.Name, "", dEnv) + err = actions.CloneRemote(ctx, srcDB, r.Name, "", false, dEnv) if err != nil { mr.Errhand(err) } From 4276eb6f0fef2c088f6e7181380799811f9fce23 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 16:11:48 -0800 Subject: [PATCH 08/63] New proto gen --- go/cmd/dolt/commands/sqlserver/server.go | 44 ++++++++++++++ .../eventsapi/v1alpha1/client_event.pb.go | 5 +- .../v1alpha1/client_event_grpc.pb.go | 1 - .../eventsapi/v1alpha1/event_constants.pb.go | 57 +++++++++++-------- .../remotesapi/v1alpha1/chunkstore.pb.go | 5 +- .../remotesapi/v1alpha1/chunkstore_grpc.pb.go | 1 - .../remotesapi/v1alpha1/credentials.pb.go | 5 +- .../v1alpha1/credentials_grpc.pb.go | 1 - .../replicationapi/v1alpha1/replication.pb.go | 5 +- .../v1alpha1/replication_grpc.pb.go | 1 - 10 files changed, 84 insertions(+), 41 deletions(-) diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index c4f771f261..d381356c9c 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,6 +26,8 @@ import ( "strings" "time" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" + "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -123,6 +125,11 @@ func Serve( }, } controller.Register(InitLogging) + + emitHeartbeat := &heartbeatService{ + dEnv: dEnv, + } + controller.Register(emitHeartbeat) fs := dEnv.FS InitDataDir := &svcs.AnonService{ @@ -561,6 +568,43 @@ func Serve( return nil, controller.WaitForStop() } +type heartbeatService struct { + dEnv *env.DoltEnv + eventEmitter *events.GrpcEmitter +} + +func (h *heartbeatService) Init(ctx context.Context) error { + h.eventEmitter = commands.GRPCEventEmitterForEnv(h.dEnv) + return nil +} + +func (h *heartbeatService) Stop() error {return nil} + +func (h *heartbeatService) Run(ctx context.Context) { + ticker := time.NewTicker(24 * time.Hour) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + h.eventEmitter.LogEvents("TODO", []*eventsapi.ClientEvent{ + { + Id: "", + StartTime: nil, + EndTime: nil, + Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, + Attributes: nil, + Metrics: nil, + }, + }) + } + } +} + +var _ svcs.Service = &heartbeatService{} + func persistServerLocalCreds(port int, dEnv *env.DoltEnv) (*LocalCreds, error) { creds := NewLocalCreds(port) err := WriteLocalCreds(dEnv.FS, creds) diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go index 6e09d77b48..50e349ba74 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go @@ -23,13 +23,12 @@ package eventsapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go index 8a09ad1cf6..085a9fda2b 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go @@ -24,7 +24,6 @@ package eventsapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go index 188068cfc1..233ed21896 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go @@ -23,11 +23,10 @@ package eventsapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( @@ -155,6 +154,7 @@ const ( ClientEventType_STASH_POP ClientEventType = 60 ClientEventType_SHOW ClientEventType = 61 ClientEventType_PROFILE ClientEventType = 62 + ClientEventType_SQL_SERVER_HEARTBEAT ClientEventType = 63 ) // Enum value maps for ClientEventType. @@ -223,6 +223,7 @@ var ( 60: "STASH_POP", 61: "SHOW", 62: "PROFILE", + 63: "SQL_SERVER_HEARTBEAT", } ClientEventType_value = map[string]int32{ "TYPE_UNSPECIFIED": 0, @@ -288,6 +289,7 @@ var ( "STASH_POP": 60, "SHOW": 61, "PROFILE": 62, + "SQL_SERVER_HEARTBEAT": 63, } ) @@ -421,6 +423,7 @@ type AppID int32 const ( AppID_APP_ID_UNSPECIFIED AppID = 0 AppID_APP_DOLT AppID = 1 + AppID_APP_DOLTGRES AppID = 2 ) // Enum value maps for AppID. @@ -428,10 +431,12 @@ var ( AppID_name = map[int32]string{ 0: "APP_ID_UNSPECIFIED", 1: "APP_DOLT", + 2: "APP_DOLTGRES", } AppID_value = map[string]int32{ "APP_ID_UNSPECIFIED": 0, "APP_DOLT": 1, + "APP_DOLTGRES": 2, } ) @@ -475,7 +480,7 @@ var file_dolt_services_eventsapi_v1alpha1_event_constants_proto_rawDesc = []byte 0x52, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x41, 0x52, 0x57, - 0x49, 0x4e, 0x10, 0x03, 0x2a, 0xfd, 0x07, 0x0a, 0x0f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, + 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x97, 0x08, 0x0a, 0x0f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, @@ -539,27 +544,29 @@ var file_dolt_services_eventsapi_v1alpha1_event_constants_proto_rawDesc = []byte 0x0a, 0x0a, 0x53, 0x54, 0x41, 0x53, 0x48, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x3b, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x54, 0x41, 0x53, 0x48, 0x5f, 0x50, 0x4f, 0x50, 0x10, 0x3c, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x48, 0x4f, 0x57, 0x10, 0x3d, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x46, 0x49, - 0x4c, 0x45, 0x10, 0x3e, 0x2a, 0x6a, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x49, 0x44, - 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x59, 0x54, 0x45, - 0x53, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, - 0x0a, 0x13, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x4d, 0x53, 0x5f, 0x45, 0x4c, - 0x41, 0x50, 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4d, 0x4f, 0x54, - 0x45, 0x41, 0x50, 0x49, 0x5f, 0x52, 0x50, 0x43, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, - 0x2a, 0x45, 0x0a, 0x0b, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x12, - 0x19, 0x0a, 0x15, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, - 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x55, 0x52, 0x4c, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x45, 0x10, - 0x02, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x2a, 0x2d, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x44, - 0x12, 0x16, 0x0a, 0x12, 0x41, 0x50, 0x50, 0x5f, 0x49, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x50, 0x50, 0x5f, - 0x44, 0x4f, 0x4c, 0x54, 0x10, 0x01, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x68, 0x75, 0x62, 0x2f, 0x64, 0x6f, 0x6c, - 0x74, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, - 0x6f, 0x6c, 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x4c, 0x45, 0x10, 0x3e, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x51, 0x4c, 0x5f, 0x53, 0x45, 0x52, 0x56, + 0x45, 0x52, 0x5f, 0x48, 0x45, 0x41, 0x52, 0x54, 0x42, 0x45, 0x41, 0x54, 0x10, 0x3f, 0x2a, 0x6a, + 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, + 0x54, 0x52, 0x49, 0x43, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x59, 0x54, 0x45, 0x53, 0x5f, 0x44, 0x4f, 0x57, 0x4e, + 0x4c, 0x4f, 0x41, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x44, 0x4f, 0x57, 0x4e, + 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x4d, 0x53, 0x5f, 0x45, 0x4c, 0x41, 0x50, 0x53, 0x45, 0x44, 0x10, + 0x02, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x41, 0x50, 0x49, 0x5f, 0x52, + 0x50, 0x43, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x2a, 0x45, 0x0a, 0x0b, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x54, 0x54, + 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x55, + 0x52, 0x4c, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x45, 0x10, 0x02, 0x22, 0x04, 0x08, 0x01, 0x10, + 0x01, 0x2a, 0x3f, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x50, + 0x50, 0x5f, 0x49, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x50, 0x50, 0x5f, 0x44, 0x4f, 0x4c, 0x54, 0x10, 0x01, + 0x12, 0x10, 0x0a, 0x0c, 0x41, 0x50, 0x50, 0x5f, 0x44, 0x4f, 0x4c, 0x54, 0x47, 0x52, 0x45, 0x53, + 0x10, 0x02, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x68, 0x75, 0x62, 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x2f, 0x67, 0x6f, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x6f, 0x6c, 0x74, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go index dde8ed815b..0fc8ae7e15 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go @@ -21,12 +21,11 @@ package remotesapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go index 28cfc20104..828da30d62 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go @@ -22,7 +22,6 @@ package remotesapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go index 7c2e689b33..8164b2bb9a 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go @@ -21,11 +21,10 @@ package remotesapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go index 8ae0dfc1eb..e859388139 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go @@ -22,7 +22,6 @@ package remotesapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go index 6ac797942a..c0dd217790 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go @@ -21,11 +21,10 @@ package replicationapi import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go index 275cc34a39..3af833933d 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go @@ -22,7 +22,6 @@ package replicationapi import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" From 7b2768c79cd58bfb97a3ad0e8c21a438b64cfd89 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 16:13:42 -0800 Subject: [PATCH 09/63] Formatting --- go/cmd/dolt/commands/send_metrics.go | 2 +- go/cmd/dolt/commands/sqlserver/server.go | 10 +++++----- go/cmd/dolt/dolt.go | 20 +++++++++---------- .../eventsapi/v1alpha1/client_event.pb.go | 5 +++-- .../v1alpha1/client_event_grpc.pb.go | 1 + .../eventsapi/v1alpha1/event_constants.pb.go | 5 +++-- .../remotesapi/v1alpha1/chunkstore.pb.go | 5 +++-- .../remotesapi/v1alpha1/chunkstore_grpc.pb.go | 1 + .../remotesapi/v1alpha1/credentials.pb.go | 5 +++-- .../v1alpha1/credentials_grpc.pb.go | 1 + .../replicationapi/v1alpha1/replication.pb.go | 5 +++-- .../v1alpha1/replication_grpc.pb.go | 1 + 12 files changed, 35 insertions(+), 26 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 1ca5107c8c..8229925e15 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -21,11 +21,11 @@ import ( "strconv" "time" - "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/fatih/color" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" + "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index d381356c9c..82ffc2b687 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,8 +26,6 @@ import ( "strings" "time" - eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" - "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -42,6 +40,7 @@ import ( "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/cmd/dolt/commands/engine" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/remotesrv" "github.com/dolthub/dolt/go/libraries/doltcore/sqle" @@ -50,6 +49,7 @@ import ( _ "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" "github.com/dolthub/dolt/go/libraries/doltcore/sqlserver" + "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/svcs" ) @@ -125,7 +125,7 @@ func Serve( }, } controller.Register(InitLogging) - + emitHeartbeat := &heartbeatService{ dEnv: dEnv, } @@ -569,7 +569,7 @@ func Serve( } type heartbeatService struct { - dEnv *env.DoltEnv + dEnv *env.DoltEnv eventEmitter *events.GrpcEmitter } @@ -578,7 +578,7 @@ func (h *heartbeatService) Init(ctx context.Context) error { return nil } -func (h *heartbeatService) Stop() error {return nil} +func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { ticker := time.NewTicker(24 * time.Hour) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index fa9067f478..33d12c7269 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -463,7 +463,7 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - + defer func() { metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) @@ -749,16 +749,16 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). -func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { - userHomeDir, err := dEnv.GetUserHomeDir() - if err != nil { - return err - } +// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). +func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { + userHomeDir, err := dEnv.GetUserHomeDir() + if err != nil { + return err + } - // TODO: handle stdio output - _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) - return nil + // TODO: handle stdio output + _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) + return nil } func shouldFlushEvents(command string) bool { diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go index 50e349ba74..6e09d77b48 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event.pb.go @@ -23,12 +23,13 @@ package eventsapi import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" durationpb "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go index 085a9fda2b..8a09ad1cf6 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/client_event_grpc.pb.go @@ -24,6 +24,7 @@ package eventsapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go index 233ed21896..a3e22c7a62 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go @@ -23,10 +23,11 @@ package eventsapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go index 0fc8ae7e15..dde8ed815b 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore.pb.go @@ -21,11 +21,12 @@ package remotesapi import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go index 828da30d62..28cfc20104 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/chunkstore_grpc.pb.go @@ -22,6 +22,7 @@ package remotesapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go index 8164b2bb9a..7c2e689b33 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials.pb.go @@ -21,10 +21,11 @@ package remotesapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go index e859388139..8ae0dfc1eb 100644 --- a/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go +++ b/go/gen/proto/dolt/services/remotesapi/v1alpha1/credentials_grpc.pb.go @@ -22,6 +22,7 @@ package remotesapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go index c0dd217790..6ac797942a 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication.pb.go @@ -21,10 +21,11 @@ package replicationapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go index 3af833933d..275cc34a39 100644 --- a/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go +++ b/go/gen/proto/dolt/services/replicationapi/v1alpha1/replication_grpc.pb.go @@ -22,6 +22,7 @@ package replicationapi import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" From 124967af38e44cd8d7f2d0c3f3f7e9dafafe0d89 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:11:25 -0800 Subject: [PATCH 10/63] SQL server heartbeater --- go/cmd/dolt/commands/send_metrics.go | 51 +++++++++++++----------- go/cmd/dolt/commands/sqlserver/server.go | 39 +++++++++++------- go/libraries/events/events.go | 6 +-- 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 8229925e15..1319f6eb01 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -17,7 +17,6 @@ package commands import ( "context" "fmt" - "log" "strconv" "time" @@ -138,36 +137,40 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin return flusher.Flush(ctx) } -// GRPCEventEmitterForEnv returns an event emitter for the given environment +// GRPCEventEmitterForEnv returns an event emitter for the given environment, or nil if the environment cannot +// provide one func GRPCEventEmitterForEnv(dEnv *env.DoltEnv) *events.GrpcEmitter { - host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) - portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) - insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") - - port, err := strconv.ParseUint(portStr, 10, 16) - - if err != nil { - log.Println(color.YellowString("The config value of '%s' is '%s' which is not a valid port.", env.MetricsPort, portStr)) - return nil - } - - insecure, err := strconv.ParseBool(insecureStr) - - if err != nil { - log.Println(color.YellowString("The config value of '%s' is '%s' which is not a valid true/false value", env.MetricsInsecure, insecureStr)) - } - - hostAndPort := fmt.Sprintf("%s:%d", host, port) - cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ - Endpoint: hostAndPort, - Insecure: insecure, - }) + cfg, err := GRPCEventRemoteConfigForEnv(dEnv) if err != nil { return nil } + conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) if err != nil { return nil } return events.NewGrpcEmitter(conn) } + +func GRPCEventRemoteConfigForEnv(dEnv *env.DoltEnv) (dbfactory.GRPCRemoteConfig, error) { + host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) + portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) + insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") + + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + insecure, _ := strconv.ParseBool(insecureStr) + + hostAndPort := fmt.Sprintf("%s:%d", host, port) + cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ + Endpoint: hostAndPort, + Insecure: insecure, + }) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + return cfg, err +} diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 82ffc2b687..7f7e29d966 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -33,8 +34,10 @@ import ( "github.com/dolthub/go-mysql-server/sql/plan" "github.com/dolthub/go-mysql-server/sql/types" "github.com/dolthub/vitess/go/mysql" + "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sirupsen/logrus" + "google.golang.org/grpc" goerrors "gopkg.in/src-d/go-errors.v1" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -126,9 +129,7 @@ func Serve( } controller.Register(InitLogging) - emitHeartbeat := &heartbeatService{ - dEnv: dEnv, - } + emitHeartbeat := newHeartbeatService(version, dEnv) controller.Register(emitHeartbeat) fs := dEnv.FS @@ -569,16 +570,17 @@ func Serve( } type heartbeatService struct { - dEnv *env.DoltEnv - eventEmitter *events.GrpcEmitter + version string + cfg dbfactory.GRPCRemoteConfig } -func (h *heartbeatService) Init(ctx context.Context) error { - h.eventEmitter = commands.GRPCEventEmitterForEnv(h.dEnv) - return nil +func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { + cfg, _ := commands.GRPCEventRemoteConfigForEnv(dEnv) + return &heartbeatService{version: version, cfg: cfg} } -func (h *heartbeatService) Stop() error { return nil } +func (h *heartbeatService) Init(ctx context.Context) error { return nil } +func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { ticker := time.NewTicker(24 * time.Hour) @@ -589,16 +591,23 @@ func (h *heartbeatService) Run(ctx context.Context) { case <-ctx.Done(): return case <-ticker.C: - h.eventEmitter.LogEvents("TODO", []*eventsapi.ClientEvent{ + conn, err := grpc.Dial(h.cfg.Endpoint, h.cfg.DialOptions...) + if err != nil { + continue + } + + eventEmitter := events.NewGrpcEmitter(conn) + t := events.NowTimestamp() + _ = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { - Id: "", - StartTime: nil, - EndTime: nil, + Id: uuid.New().String(), + StartTime: t, + EndTime: t, Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, - Attributes: nil, - Metrics: nil, }, }) + + _ = conn.Close() } } } diff --git a/go/libraries/events/events.go b/go/libraries/events/events.go index 2a98096eb4..723e1aec40 100644 --- a/go/libraries/events/events.go +++ b/go/libraries/events/events.go @@ -27,7 +27,7 @@ import ( // EventNowFunc function is used to get the current time and can be overridden for testing. var EventNowFunc = time.Now -func nowTimestamp() *timestamppb.Timestamp { +func NowTimestamp() *timestamppb.Timestamp { now := EventNowFunc() ts := timestamppb.New(now) err := ts.CheckValid() @@ -51,7 +51,7 @@ func NewEvent(ceType eventsapi.ClientEventType) *Event { return &Event{ ce: &eventsapi.ClientEvent{ Id: uuid.New().String(), - StartTime: nowTimestamp(), + StartTime: NowTimestamp(), Type: ceType, }, m: &sync.Mutex{}, @@ -83,7 +83,7 @@ func (evt *Event) close() *eventsapi.ClientEvent { evt.m.Lock() defer evt.m.Unlock() - evt.ce.EndTime = nowTimestamp() + evt.ce.EndTime = NowTimestamp() for k, v := range evt.attributes { evt.ce.Attributes = append(evt.ce.Attributes, &eventsapi.ClientEventAttribute{Id: k, Value: v}) From bca9aff6423d00ec30e40cadd13a08f2f9c98458 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:29:49 -0800 Subject: [PATCH 11/63] Revert to previous behavior of invoking the send metrics command --- go/cmd/dolt/dolt.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 33d12c7269..9739a47345 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -23,6 +23,8 @@ import ( "net/http" _ "net/http/pprof" "os" + "os/exec" + "path/filepath" "strconv" "time" @@ -477,7 +479,7 @@ func runMain() int { // flush events if len(args) > 0 && shouldFlushEvents(args[0]) { - _ = processEventsDir(ctx, dEnv) + _ = processEventsDir() } }() @@ -749,15 +751,25 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir flushes all logged events to an appropriate event emitter (typically a gRPC client). -func processEventsDir(ctx context.Context, dEnv *env.DoltEnv) error { - userHomeDir, err := dEnv.GetUserHomeDir() +// processEventsDir flushes all logged events in a separate process. +// This is done without blocking so that the main process can exit immediately in the case of a slow network. +func processEventsDir() error { + path, err := os.Executable() if err != nil { return err } - // TODO: handle stdio output - _ = commands.FlushLoggedEvents(ctx, dEnv, userHomeDir, false) + absPath, err := filepath.Abs(path) + if err != nil { + return err + } + + cmd := exec.Command(absPath, commands.SendMetricsCommand) + + if err := cmd.Start(); err != nil { + return err + } + return nil } From de38dcce475302ce5da1c03401c973c2def9b099 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:42:22 -0800 Subject: [PATCH 12/63] Cleanup --- go/cmd/dolt/commands/sqlserver/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 7f7e29d966..b90f31a1b1 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -129,8 +129,7 @@ func Serve( } controller.Register(InitLogging) - emitHeartbeat := newHeartbeatService(version, dEnv) - controller.Register(emitHeartbeat) + controller.Register(newHeartbeatService(version, dEnv)) fs := dEnv.FS InitDataDir := &svcs.AnonService{ @@ -569,6 +568,7 @@ func Serve( return nil, controller.WaitForStop() } +// heartbeatService is a service that sends a heartbeat event to the metrics server once a day type heartbeatService struct { version string cfg dbfactory.GRPCRemoteConfig From d31758468d06837efb0f69e335130e29567cb168 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 17:44:27 -0800 Subject: [PATCH 13/63] go mod cleanup --- go/go.mod | 14 +++++++------- go/go.sum | 17 ++++++++--------- integration-tests/go-sql-server-driver/go.mod | 2 +- integration-tests/go-sql-server-driver/go.sum | 11 ++--------- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/go/go.mod b/go/go.mod index ff7c300a18..3f0bd990c9 100644 --- a/go/go.mod +++ b/go/go.mod @@ -16,17 +16,16 @@ require ( github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488 github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f - github.com/dustin/go-humanize v1.0.0 + github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.13.0 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/go-sql-driver/mysql v1.7.2-0.20230713085235-0b18dac46f7f github.com/gocraft/dbr/v2 v2.7.2 - github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 github.com/google/uuid v1.3.0 github.com/jpillora/backoff v1.0.0 github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d - github.com/mattn/go-isatty v0.0.16 + github.com/mattn/go-isatty v0.0.17 github.com/mattn/go-runewidth v0.0.13 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.5.0 @@ -36,9 +35,8 @@ require ( github.com/silvasur/buzhash v0.0.0-20160816060738-9bdec3dec7c6 github.com/sirupsen/logrus v1.8.1 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 github.com/tealeg/xlsx v1.0.5 - github.com/tklauser/go-sysconf v0.3.9 // indirect go.uber.org/zap v1.24.0 golang.org/x/crypto v0.14.0 golang.org/x/net v0.17.0 @@ -114,6 +112,7 @@ require ( github.com/go-pdf/fpdf v0.6.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect @@ -121,7 +120,7 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.10.10 // indirect + github.com/klauspost/compress v1.10.5 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/lestrrat-go/strftime v1.0.4 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect @@ -138,6 +137,7 @@ require ( github.com/tetratelabs/wazero v1.1.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect + github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/numcpus v0.3.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.24.0 // indirect @@ -147,7 +147,7 @@ require ( golang.org/x/mod v0.12.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/term v0.13.0 // indirect - golang.org/x/time v0.1.0 // indirect + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/tools v0.13.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go/go.sum b/go/go.sum index cf1ad94a2b..131c69cfb9 100644 --- a/go/go.sum +++ b/go/go.sum @@ -196,8 +196,8 @@ github.com/dolthub/swiss v0.1.0/go.mod h1:BeucyB08Vb1G9tumVN3Vp/pyY4AMUnr9p7Rz7w github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f h1:I480LKHhb4usnF3dYhp6J4ORKMrncNKaWYZvIZwlK+U= github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f/go.mod h1:IwjNXSQPymrja5pVqmfnYdcy7Uv7eNJNBPK/MEh9OOw= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= @@ -432,9 +432,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.5 h1:7q6vHIqubShURwQz8cQK6yIe/xC3IF0Vm7TGfqjewrc= github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I= -github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -476,8 +475,9 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -648,8 +648,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= github.com/tetratelabs/wazero v1.1.0 h1:EByoAhC+QcYpwSZJSs/aV0uokxPwBgKxfiokSUwAknQ= @@ -961,9 +961,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/integration-tests/go-sql-server-driver/go.mod b/integration-tests/go-sql-server-driver/go.mod index f9f6e54012..cd31fd8d09 100644 --- a/integration-tests/go-sql-server-driver/go.mod +++ b/integration-tests/go-sql-server-driver/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/dolthub/dolt/go v0.40.4 github.com/google/uuid v1.3.0 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 golang.org/x/sync v0.3.0 gopkg.in/square/go-jose.v2 v2.5.1 gopkg.in/yaml.v3 v3.0.1 diff --git a/integration-tests/go-sql-server-driver/go.sum b/integration-tests/go-sql-server-driver/go.sum index 07862eae62..f088962fe0 100644 --- a/integration-tests/go-sql-server-driver/go.sum +++ b/integration-tests/go-sql-server-driver/go.sum @@ -1,6 +1,5 @@ github.com/creasty/defaults v1.6.0 h1:ltuE9cfphUtlrBeomuu8PEyISTXnxqkBIoQfXgv7BSc= github.com/creasty/defaults v1.6.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-sql-driver/mysql v1.7.2-0.20230713085235-0b18dac46f7f h1:4+t8Qb99xUG/Ea00cQAiQl+gsjpK8ZYtAO8E76gRzQI= @@ -11,13 +10,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= @@ -28,6 +22,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From f63ad7b1a4d0d37db33f7e4b8041edd8526c52a6 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 1 Dec 2023 18:03:18 -0800 Subject: [PATCH 14/63] Added check for disabled metrics --- go/cmd/dolt/commands/sqlserver/server.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index b90f31a1b1..bbdb151efb 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -575,6 +575,12 @@ type heartbeatService struct { } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { + metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + disabled, err := strconv.ParseBool(metricsDisabled) + if err != nil || disabled { + return &heartbeatService{} // will be defunct on Run() + } + cfg, _ := commands.GRPCEventRemoteConfigForEnv(dEnv) return &heartbeatService{version: version, cfg: cfg} } @@ -583,6 +589,11 @@ func (h *heartbeatService) Init(ctx context.Context) error { return nil } func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { + // Faulty config settings or disabled metrics can cause us to not have a valid endpoint + if h.cfg.Endpoint == "" { + return + } + ticker := time.NewTicker(24 * time.Hour) defer ticker.Stop() @@ -598,7 +609,7 @@ func (h *heartbeatService) Run(ctx context.Context) { eventEmitter := events.NewGrpcEmitter(conn) t := events.NowTimestamp() - _ = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ + err = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { Id: uuid.New().String(), StartTime: t, @@ -607,6 +618,10 @@ func (h *heartbeatService) Run(ctx context.Context) { }, }) + if err != nil { + logrus.Debugf("failed to send heartbeat event: %v", err) + } + _ = conn.Close() } } From e05f2169cfed62e989439a4b39ec472dbe3c53e5 Mon Sep 17 00:00:00 2001 From: zachmu Date: Sat, 2 Dec 2023 02:12:16 +0000 Subject: [PATCH 15/63] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/cmd/dolt/commands/send_metrics.go | 2 +- go/cmd/dolt/commands/sqlserver/server.go | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 1319f6eb01..233cd5d740 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -163,7 +163,7 @@ func GRPCEventRemoteConfigForEnv(dEnv *env.DoltEnv) (dbfactory.GRPCRemoteConfig, } insecure, _ := strconv.ParseBool(insecureStr) - + hostAndPort := fmt.Sprintf("%s:%d", host, port) cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ Endpoint: hostAndPort, diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index bbdb151efb..5f6457cceb 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,7 +26,6 @@ import ( "strings" "time" - "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -44,6 +43,7 @@ import ( "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/cmd/dolt/commands/engine" eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" + "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/remotesrv" "github.com/dolthub/dolt/go/libraries/doltcore/sqle" @@ -590,10 +590,10 @@ func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { // Faulty config settings or disabled metrics can cause us to not have a valid endpoint - if h.cfg.Endpoint == "" { + if h.cfg.Endpoint == "" { return } - + ticker := time.NewTicker(24 * time.Hour) defer ticker.Stop() @@ -606,22 +606,22 @@ func (h *heartbeatService) Run(ctx context.Context) { if err != nil { continue } - + eventEmitter := events.NewGrpcEmitter(conn) t := events.NowTimestamp() err = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { - Id: uuid.New().String(), - StartTime: t, - EndTime: t, - Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, + Id: uuid.New().String(), + StartTime: t, + EndTime: t, + Type: eventsapi.ClientEventType_SQL_SERVER_HEARTBEAT, }, }) - + if err != nil { logrus.Debugf("failed to send heartbeat event: %v", err) } - + _ = conn.Close() } } From 4ec6d2b9fe8352ecdabdc3697177a04f1fde4df0 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Mon, 4 Dec 2023 10:00:58 -0800 Subject: [PATCH 16/63] PR comments --- go/cmd/dolt/cli/arg_parser_helpers.go | 2 +- go/libraries/doltcore/env/actions/clone.go | 21 +++++++-------- integration-tests/bats/remotes.bats | 30 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/go/cmd/dolt/cli/arg_parser_helpers.go b/go/cmd/dolt/cli/arg_parser_helpers.go index eb8cd1ae06..0a04e0f20b 100644 --- a/go/cmd/dolt/cli/arg_parser_helpers.go +++ b/go/cmd/dolt/cli/arg_parser_helpers.go @@ -125,7 +125,7 @@ func CreateCloneArgParser() *argparser.ArgParser { ap.SupportsString(dbfactory.OSSCredsFileParam, "", "file", "OSS credentials file.") ap.SupportsString(dbfactory.OSSCredsProfile, "", "profile", "OSS profile to use.") ap.SupportsString(UserFlag, "u", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.") - ap.SupportsFlag(SingleBranchFlag, "", "Clone only the history leading to the tip of a single branch, either specified by --branch or the primary branch remote's HEAD points at.") + ap.SupportsFlag(SingleBranchFlag, "", "Clone only the history leading to the tip of a single branch, either specified by --branch or the remote's HEAD (default).") return ap } diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index 82d5de273a..e0cac4b902 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -214,27 +214,28 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // every branch in the remote. We iterate through local branches and // create remote refs corresponding to each of them. We delete all of // the local branches except for the one corresponding to |branch|. - for _, brnch := range branches { - if brnch.GetPath() != branch { - err := dEnv.DoltDB.DeleteBranch(ctx, brnch, nil) - if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToDeleteBranch, brnch.String(), err.Error()) - } - } else if !singleBranch || brnch.GetPath() == branch { - cs, _ := doltdb.NewCommitSpec(brnch.GetPath()) + for _, br := range branches { + if !singleBranch || (singleBranch && br.GetPath() == branch) { + cs, _ := doltdb.NewCommitSpec(br.GetPath()) cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) if err != nil { - return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, brnch.String(), err.Error()) + return fmt.Errorf("%w: %s; %s", ErrFailedToResolveBranchRef, br.String(), err.Error()) } - remoteRef := ref.NewRemoteRef(remoteName, brnch.GetPath()) + remoteRef := ref.NewRemoteRef(remoteName, br.GetPath()) err = dEnv.DoltDB.SetHeadToCommit(ctx, remoteRef, cm) if err != nil { return fmt.Errorf("%w: %s; %s", ErrFailedToCreateRemoteRef, remoteRef.String(), err.Error()) } } + if br.GetPath() != branch { + err := dEnv.DoltDB.DeleteBranch(ctx, br, nil) + if err != nil { + return fmt.Errorf("%w: %s; %s", ErrFailedToDeleteBranch, br.String(), err.Error()) + } + } } // TODO: make this interface take a DoltRef and marshal it automatically diff --git a/integration-tests/bats/remotes.bats b/integration-tests/bats/remotes.bats index 0dd65d7d5e..26dbfffb9b 100644 --- a/integration-tests/bats/remotes.bats +++ b/integration-tests/bats/remotes.bats @@ -1023,6 +1023,36 @@ create_five_remote_branches_main_and_master() { [[ ! "$output" =~ "remotes/origin/branch-two" ]] || false } +@test "remotes: clone --branch specifies which branch to clone" { + create_three_remote_branches + cd dolt-repo-clones + dolt clone --branch branch-one http://localhost:50051/test-org/test-repo + cd test-repo + run dolt branch -a + [ "$status" -eq 0 ] + [[ "$output" =~ "* branch-one" ]] || false + [[ ! "$output" =~ " main" ]] || false + [[ ! "$output" =~ " branch-two" ]] || false + [[ "$output" =~ "remotes/origin/main" ]] || false + [[ "$output" =~ "remotes/origin/branch-one" ]] || false + [[ "$output" =~ "remotes/origin/branch-two" ]] || false +} + +@test "remotes: clone --single-branch --branch does not create all remote refs" { + create_three_remote_branches + cd dolt-repo-clones + dolt clone --branch branch-one --single-branch http://localhost:50051/test-org/test-repo + cd test-repo + run dolt branch -a + [ "$status" -eq 0 ] + [[ "$output" =~ "* branch-one" ]] || false + [[ ! "$output" =~ " main" ]] || false + [[ ! "$output" =~ " branch-two" ]] || false + [[ ! "$output" =~ "remotes/origin/main" ]] || false + [[ "$output" =~ "remotes/origin/branch-one" ]] || false + [[ ! "$output" =~ "remotes/origin/branch-two" ]] || false +} + @test "remotes: fetch creates new remote refs for new remote branches" { create_main_remote_branch From 1cd686427e65d634379462aadab6989f3bb7edba Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 11:42:19 -0800 Subject: [PATCH 17/63] Pull out emit func --- go/cmd/dolt/dolt.go | 51 ++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 4015a1800b..d3b5251589 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -209,12 +209,18 @@ Dolt subcommands are in transition to using the flags listed below as global fla Not all subcommands use these flags. If your command accepts these flags without error, then they are supported. ` +const disableEventFlushEnvVar = "DOLT_DISABLE_EVENT_FLUSH" +var eventFlushDisabled = false + func init() { dumpDocsCommand.DoltCommand = doltCommand dumpDocsCommand.GlobalDocs = globalDocs dumpDocsCommand.GlobalSpecialMsg = globalSpecialMsg dumpZshCommand.DoltCommand = doltCommand dfunctions.VersionString = Version + if _, ok := os.LookupEnv(disableEventFlushEnvVar); ok { + eventFlushDisabled = true + } } const pprofServerFlag = "--pprof-server" @@ -466,23 +472,8 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - - defer func() { - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") - disabled, err := strconv.ParseBool(metricsDisabled) - if err != nil || disabled { - return - } - - // write events - emitter := events.NewFileEmitter(homeDir, dbfactory.DoltDir) - _ = emitter.LogEvents(Version, events.GlobalCollector.Close()) - - // flush events - if len(args) > 0 && shouldFlushEvents(args[0]) { - _ = processEventsDir() - } - }() + + defer emitUsageEvents(dEnv, homeDir, args) if needsWriteAccess(subcommandName) { err = reconfigIfTempFileMoveFails(dEnv) @@ -752,9 +743,31 @@ func seedGlobalRand() { rand.Seed(int64(binary.LittleEndian.Uint64(bs))) } -// processEventsDir flushes all logged events in a separate process. +// emitUsageEvents is called after a command is run to emit usage events and send them to metrics servers. +// Two controls of this behavior are possible: +// 1. The config key |metrics.disabled|, when set to |true|, disables all metrics emission +// 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. +// This is mostly used for testing. +func emitUsageEvents(dEnv *env.DoltEnv, homeDir string, args []string) { + metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + disabled, err := strconv.ParseBool(metricsDisabled) + if err != nil || disabled { + return + } + + // write events + emitter := events.NewFileEmitter(homeDir, dbfactory.DoltDir) + _ = emitter.LogEvents(Version, events.GlobalCollector.Close()) + + // flush events + if !eventFlushDisabled && len(args) > 0 && shouldFlushEvents(args[0]) { + _ = flushEventsDir() + } +} + +// flushEventsDir flushes all logged events in a separate process. // This is done without blocking so that the main process can exit immediately in the case of a slow network. -func processEventsDir() error { +func flushEventsDir() error { path, err := os.Executable() if err != nil { return err From 2b33f9c6d1f81798abfa3a328ff40b971c90b52c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 13:33:29 -0800 Subject: [PATCH 18/63] Moved some things around, wrote a factory method --- go/cmd/dolt/commands/send_metrics.go | 45 +----------- go/cmd/dolt/commands/sqlserver/server.go | 2 +- go/libraries/doltcore/env/environment.go | 4 ++ go/libraries/events/emitter.go | 87 ++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 44 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 233cd5d740..f269a87d59 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -16,20 +16,16 @@ package commands import ( "context" - "fmt" "strconv" "time" - "github.com/fatih/color" - "google.golang.org/grpc" - "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" - "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/fatih/color" ) // SendMetricsCommand is the command used for sending metrics @@ -130,47 +126,10 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin if outputToStdio { flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) } else { - grpcEmitter := GRPCEventEmitterForEnv(dEnv) + grpcEmitter := events.GRPCEmitterForConfig(dEnv) flusher = events.NewGrpcEventFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, grpcEmitter) } return flusher.Flush(ctx) } -// GRPCEventEmitterForEnv returns an event emitter for the given environment, or nil if the environment cannot -// provide one -func GRPCEventEmitterForEnv(dEnv *env.DoltEnv) *events.GrpcEmitter { - cfg, err := GRPCEventRemoteConfigForEnv(dEnv) - if err != nil { - return nil - } - - conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) - if err != nil { - return nil - } - return events.NewGrpcEmitter(conn) -} - -func GRPCEventRemoteConfigForEnv(dEnv *env.DoltEnv) (dbfactory.GRPCRemoteConfig, error) { - host := dEnv.Config.GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) - portStr := dEnv.Config.GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) - insecureStr := dEnv.Config.GetStringOrDefault(env.MetricsInsecure, "false") - - port, err := strconv.ParseUint(portStr, 10, 16) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - - insecure, _ := strconv.ParseBool(insecureStr) - - hostAndPort := fmt.Sprintf("%s:%d", host, port) - cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ - Endpoint: hostAndPort, - Insecure: insecure, - }) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - return cfg, err -} diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 5f6457cceb..de1de6785e 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -581,7 +581,7 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { return &heartbeatService{} // will be defunct on Run() } - cfg, _ := commands.GRPCEventRemoteConfigForEnv(dEnv) + cfg, _ := events.GRPCEventRemoteConfig(dEnv) return &heartbeatService{version: version, cfg: cfg} } diff --git a/go/libraries/doltcore/env/environment.go b/go/libraries/doltcore/env/environment.go index 77537b2b87..209d95d6f6 100644 --- a/go/libraries/doltcore/env/environment.go +++ b/go/libraries/doltcore/env/environment.go @@ -105,6 +105,10 @@ func (dEnv *DoltEnv) GetRemoteDB(ctx context.Context, format *types.NomsBinForma } } +func (dEnv *DoltEnv) GetConfig() config.ReadableConfig { + return dEnv.Config +} + func createRepoState(fs filesys.Filesys) (*RepoState, error) { repoState, rsErr := LoadRepoState(fs) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index cce62c2526..4352294d8e 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -18,10 +18,16 @@ import ( "context" "fmt" "io" + "os" "runtime" + "strconv" "strings" "time" + "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" + "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" + "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -32,12 +38,27 @@ import ( var Application = eventsapi.AppID_APP_DOLT +const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" +const ( + EmitterTypeNull = "null" + EmitterTypeWriter = "writer" + EmitterTypeGrpc = "grpc" + EmitterTypeFile = "file" +) + // Emitter is an interface used for processing a batch of events type Emitter interface { // LogEvents takes a batch of events and processes them LogEvents(version string, evts []*eventsapi.ClientEvent) error } +// EmitterConfigProvider is an interface used to get the configuration to create an emitter +type EmitterConfigProvider interface { + GetGRPCDialParams(config grpcendpoint.Config) (dbfactory.GRPCRemoteConfig, error) + GetConfig() config.ReadableConfig + GetUserHomeDir() (string, error) +} + // NullEmitter is an emitter that drops events type NullEmitter struct{} @@ -149,3 +170,69 @@ func (fe *FileEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return nil } + +// NewEmitter returns an emitter for the given configuration provider, keyed off the DOLT_EVENTS_EMITTER environment +// variable. If it's not set, defaults to a file-based emitter. +func NewEmitter(pro EmitterConfigProvider) (Emitter, error) { + envVarType, ok := os.LookupEnv(EmitterTypeEnvVar) + if !ok { + envVarType = EmitterTypeFile + } + + switch envVarType { + case EmitterTypeNull: + return NullEmitter{}, nil + case EmitterTypeWriter: + return WriterEmitter{Wr: os.Stdout}, nil + case EmitterTypeGrpc: + return GRPCEmitterForConfig(pro), nil + case EmitterTypeFile: + homeDir, err := pro.GetUserHomeDir() + if err != nil { + return nil, err + } + return NewFileEmitter(homeDir, dbfactory.DoltDir), nil + default: + return nil, fmt.Errorf("unknown emitter type: %s", envVarType) + } +} + +// GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot +// provide one +func GRPCEmitterForConfig(pro EmitterConfigProvider) *GrpcEmitter { + cfg, err := GRPCEventRemoteConfig(pro) + if err != nil { + return nil + } + + conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) + if err != nil { + return nil + } + return NewGrpcEmitter(conn) +} + +// GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider +func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { + host := pro.GetConfig().GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) + portStr := pro.GetConfig().GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) + insecureStr := pro.GetConfig().GetStringOrDefault(env.MetricsInsecure, "false") + + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + insecure, _ := strconv.ParseBool(insecureStr) + + hostAndPort := fmt.Sprintf("%s:%d", host, port) + cfg, err := pro.GetGRPCDialParams(grpcendpoint.Config{ + Endpoint: hostAndPort, + Insecure: insecure, + }) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + return cfg, nil +} From 58bb930c95a50c6b8969c578d8383997cdf26aeb Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 13:55:52 -0800 Subject: [PATCH 19/63] Moved config keys out of env package --- go/cmd/dolt/cli/command.go | 7 +-- go/cmd/dolt/commands/commit.go | 11 ++-- go/cmd/dolt/commands/credcmds/check.go | 5 +- go/cmd/dolt/commands/credcmds/import.go | 13 ++--- go/cmd/dolt/commands/credcmds/new.go | 4 +- go/cmd/dolt/commands/credcmds/use.go | 3 +- go/cmd/dolt/commands/init.go | 19 +++---- go/cmd/dolt/commands/init_test.go | 9 ++-- go/cmd/dolt/commands/login.go | 17 ++++--- go/cmd/dolt/commands/merge.go | 5 +- go/cmd/dolt/commands/pull.go | 5 +- go/cmd/dolt/commands/remote_test.go | 6 +-- go/cmd/dolt/commands/send_metrics.go | 3 +- go/cmd/dolt/commands/sqlserver/server.go | 3 +- go/cmd/dolt/dolt.go | 2 +- .../doltcore/dtestutils/environment.go | 5 +- .../dtestutils/testcommands/multienv.go | 5 +- go/libraries/doltcore/env/actions/clone.go | 5 +- go/libraries/doltcore/env/config.go | 32 ++---------- go/libraries/doltcore/env/config_test.go | 48 ++++++++--------- go/libraries/doltcore/env/environment.go | 11 ++-- .../doltcore/env/multi_repo_env_test.go | 5 +- go/libraries/doltcore/env/remotes.go | 2 +- .../doltcore/sqle/dprocedures/dolt_push.go | 3 +- go/libraries/doltcore/sqle/dsess/session.go | 4 +- go/libraries/doltcore/sqle/testutil.go | 4 +- go/libraries/events/emitter.go | 10 ++-- go/libraries/utils/config/keys.go | 51 +++++++++++++++++++ 28 files changed, 170 insertions(+), 127 deletions(-) create mode 100755 go/libraries/utils/config/keys.go diff --git a/go/cmd/dolt/cli/command.go b/go/cmd/dolt/cli/command.go index 51f0bc48d0..60bbab53fb 100644 --- a/go/cmd/dolt/cli/command.go +++ b/go/cmd/dolt/cli/command.go @@ -22,6 +22,7 @@ import ( "strings" "syscall" + config "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" @@ -293,14 +294,14 @@ fatal: empty ident name not allowed // CheckUserNameAndEmail returns true if the user name and email are set for this environment, or prints an error and // returns false if not. -func CheckUserNameAndEmail(config *env.DoltCliConfig) bool { - _, err := config.GetString(env.UserEmailKey) +func CheckUserNameAndEmail(cfg *env.DoltCliConfig) bool { + _, err := cfg.GetString(config.UserEmailKey) if err != nil { PrintErr(userNameRequiredError) return false } - _, err = config.GetString(env.UserNameKey) + _, err = cfg.GetString(config.UserNameKey) if err != nil { PrintErr(userNameRequiredError) return false diff --git a/go/cmd/dolt/commands/commit.go b/go/cmd/dolt/commands/commit.go index bddeb6f672..372d6a8396 100644 --- a/go/cmd/dolt/commands/commit.go +++ b/go/cmd/dolt/commands/commit.go @@ -22,6 +22,7 @@ import ( "os" "strings" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -275,17 +276,17 @@ func handleCommitErr(sqlCtx *sql.Context, queryist cli.Queryist, err error, usag } if err == datas.ErrNameNotConfigured { - bdr := errhand.BuildDError("Could not determine %s.", env.UserNameKey) + bdr := errhand.BuildDError("Could not determine %s.", config.UserNameKey) bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", env.UserNameKey) + bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey) return HandleVErrAndExitCode(bdr.Build(), usage) } if err == datas.ErrEmailNotConfigured { - bdr := errhand.BuildDError("Could not determine %s.", env.UserEmailKey) + bdr := errhand.BuildDError("Could not determine %s.", config.UserEmailKey) bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey) + bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey) return HandleVErrAndExitCode(bdr.Build(), usage) } @@ -355,7 +356,7 @@ func getCommitMessageFromEditor(sqlCtx *sql.Context, queryist cli.Queryist, sugg backupEd = ed } // try getting Dolt config core.editor - editorStr := cliCtx.Config().GetStringOrDefault(env.DoltEditor, backupEd) + editorStr := cliCtx.Config().GetStringOrDefault(config.DoltEditor, backupEd) cli.ExecuteWithStdioRestored(func() { commitMsg, cErr := editor.OpenCommitEditor(editorStr, initialMsg) diff --git a/go/cmd/dolt/commands/credcmds/check.go b/go/cmd/dolt/commands/credcmds/check.go index 4155596bf6..edb29fe30e 100644 --- a/go/cmd/dolt/commands/credcmds/check.go +++ b/go/cmd/dolt/commands/credcmds/check.go @@ -19,6 +19,7 @@ import ( "fmt" "net" + "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -101,8 +102,8 @@ func loadEndpoint(dEnv *env.DoltEnv, apr *argparser.ArgParseResults) (string, st return getHostFromEndpoint(earg), earg } - host := dEnv.Config.GetStringOrDefault(env.RemotesApiHostKey, env.DefaultRemotesApiHost) - port := dEnv.Config.GetStringOrDefault(env.RemotesApiHostPortKey, env.DefaultRemotesApiPort) + host := dEnv.Config.GetStringOrDefault(config.RemotesApiHostKey, env.DefaultRemotesApiHost) + port := dEnv.Config.GetStringOrDefault(config.RemotesApiHostPortKey, env.DefaultRemotesApiPort) return host, fmt.Sprintf("%s:%s", host, port) } diff --git a/go/cmd/dolt/commands/credcmds/import.go b/go/cmd/dolt/commands/credcmds/import.go index 9323a7a655..5c3251e651 100644 --- a/go/cmd/dolt/commands/credcmds/import.go +++ b/go/cmd/dolt/commands/credcmds/import.go @@ -20,6 +20,7 @@ import ( "io" "os" + "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -149,17 +150,17 @@ func updateProfileWithCredentials(ctx context.Context, dEnv *env.DoltEnv, c cred panic("Should have global config here...") } - if _, err := gcfg.GetString(env.UserNameKey); err == nil { + if _, err := gcfg.GetString(config.UserNameKey); err == nil { // Already has a name... return nil } - if _, err := gcfg.GetString(env.UserEmailKey); err == nil { + if _, err := gcfg.GetString(config.UserEmailKey); err == nil { // Already has an email... return nil } - host := dEnv.Config.GetStringOrDefault(env.RemotesApiHostKey, env.DefaultRemotesApiHost) - port := dEnv.Config.GetStringOrDefault(env.RemotesApiHostPortKey, env.DefaultRemotesApiPort) + host := dEnv.Config.GetStringOrDefault(config.RemotesApiHostKey, env.DefaultRemotesApiHost) + port := dEnv.Config.GetStringOrDefault(config.RemotesApiHostPortKey, env.DefaultRemotesApiPort) hostAndPort := fmt.Sprintf("%s:%s", host, port) cfg, err := dEnv.GetGRPCDialParams(grpcendpoint.Config{ Endpoint: hostAndPort, @@ -178,8 +179,8 @@ func updateProfileWithCredentials(ctx context.Context, dEnv *env.DoltEnv, c cred return fmt.Errorf("error: unable to call WhoAmI endpoint: %w", err) } userUpdates := map[string]string{ - env.UserNameKey: resp.DisplayName, - env.UserEmailKey: resp.EmailAddress, + config.UserNameKey: resp.DisplayName, + config.UserEmailKey: resp.EmailAddress, } return gcfg.SetStrings(userUpdates) } diff --git a/go/cmd/dolt/commands/credcmds/new.go b/go/cmd/dolt/commands/credcmds/new.go index 71ee06e538..0979b994c0 100644 --- a/go/cmd/dolt/commands/credcmds/new.go +++ b/go/cmd/dolt/commands/credcmds/new.go @@ -100,9 +100,9 @@ func updateConfigToUseNewCredIfNoExistingCred(dEnv *env.DoltEnv, dCreds creds.Do panic("global config not found. Should create it here if this is a thing.") } - _, err := gcfg.GetString(env.UserCreds) + _, err := gcfg.GetString(config.UserCreds) if err == config.ErrConfigParamNotFound { - return gcfg.SetStrings(map[string]string{env.UserCreds: dCreds.KeyIDBase32Str()}) + return gcfg.SetStrings(map[string]string{config.UserCreds: dCreds.KeyIDBase32Str()}) } else { return err } diff --git a/go/cmd/dolt/commands/credcmds/use.go b/go/cmd/dolt/commands/credcmds/use.go index fd16eedd9d..8189677883 100644 --- a/go/cmd/dolt/commands/credcmds/use.go +++ b/go/cmd/dolt/commands/credcmds/use.go @@ -25,6 +25,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) var useDocs = cli.CommandDocumentationContent{ @@ -95,7 +96,7 @@ func (cmd UseCmd) Exec(ctx context.Context, commandStr string, args []string, dE if !hasGCfg { panic("global config not found. Should create it here if this is a thing.") } - err := gcfg.SetStrings(map[string]string{env.UserCreds: cred.KeyIDBase32Str()}) + err := gcfg.SetStrings(map[string]string{config.UserCreds: cred.KeyIDBase32Str()}) if err != nil { verr = errhand.BuildDError("error: updating user credentials in config").AddCause(err).Build() } diff --git a/go/cmd/dolt/commands/init.go b/go/cmd/dolt/commands/init.go index 761557d424..ea4c451c27 100644 --- a/go/cmd/dolt/commands/init.go +++ b/go/cmd/dolt/commands/init.go @@ -19,6 +19,7 @@ import ( "fmt" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -76,10 +77,10 @@ func (cmd InitCmd) Docs() *cli.CommandDocumentation { func (cmd InitCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithMaxArgs(cmd.Name(), 0) - ap.SupportsString(usernameParamName, "", "name", fmt.Sprintf("The name used in commits to this repo. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", env.UserNameKey)) - ap.SupportsString(emailParamName, "", "email", fmt.Sprintf("The email address used. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", env.UserEmailKey)) + ap.SupportsString(usernameParamName, "", "name", fmt.Sprintf("The name used in commits to this repo. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", config.UserNameKey)) + ap.SupportsString(emailParamName, "", "email", fmt.Sprintf("The email address used. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config.", config.UserEmailKey)) ap.SupportsString(cli.DateParam, "", "date", "Specify the date used in the initial commit. If not specified the current system time is used.") - ap.SupportsString(initBranchParamName, "b", "branch", fmt.Sprintf("The branch name used to initialize this database. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config. If unset, the default initialized branch will be named '%s'.", env.InitBranchName, env.DefaultInitBranch)) + ap.SupportsString(initBranchParamName, "b", "branch", fmt.Sprintf("The branch name used to initialize this database. If not provided will be taken from {{.EmphasisLeft}}%s{{.EmphasisRight}} in the global config. If unset, the default initialized branch will be named '%s'.", config.InitBranchName, env.DefaultInitBranch)) ap.SupportsFlag(newFormatFlag, "", fmt.Sprintf("Specify this flag to use the new storage format (%s).", types.Format_DOLT.VersionString())) ap.SupportsFlag(oldFormatFlag, "", fmt.Sprintf("Specify this flag to use the old storage format (%s).", types.Format_LD_1.VersionString())) ap.SupportsFlag(funHashFlag, "", "") // This flag is an easter egg. We can't currently prevent it from being listed in the help, but the description is deliberately left blank. @@ -123,8 +124,8 @@ func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, d } } - name = dEnv.Config.IfEmptyUseConfig(name, env.UserNameKey) - email = dEnv.Config.IfEmptyUseConfig(email, env.UserEmailKey) + name = dEnv.Config.IfEmptyUseConfig(name, config.UserNameKey) + email = dEnv.Config.IfEmptyUseConfig(email, config.UserEmailKey) if initBranch == "" { initBranch = env.GetDefaultInitBranch(dEnv.Config) } @@ -133,14 +134,14 @@ func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, d cli.PrintErrln( color.RedString("Could not determine %[1]s. "+ "Use the init parameter --name \"FIRST LAST\" to set it for this repo, "+ - "or dolt config --global --add %[1]s \"FIRST LAST\"", env.UserNameKey)) + "or dolt config --global --add %[1]s \"FIRST LAST\"", config.UserNameKey)) usage() return 1 } else if email == "" { cli.PrintErrln( color.RedString("Could not determine %[1]s. "+ "Use the init parameter --email \"EMAIL_ADDRESS\" to set it for this repo, "+ - "or dolt config --global --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey)) + "or dolt config --global --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey)) usage() return 1 } @@ -169,10 +170,10 @@ func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, d configuration := make(map[string]string) if apr.Contains(usernameParamName) { - configuration[env.UserNameKey] = name + configuration[config.UserNameKey] = name } if apr.Contains(emailParamName) { - configuration[env.UserEmailKey] = email + configuration[config.UserEmailKey] = email } if len(configuration) > 0 { err = dEnv.Config.WriteableConfig().SetStrings(configuration) diff --git a/go/cmd/dolt/commands/init_test.go b/go/cmd/dolt/commands/init_test.go index 4973b2e49b..f0fba3f519 100644 --- a/go/cmd/dolt/commands/init_test.go +++ b/go/cmd/dolt/commands/init_test.go @@ -18,6 +18,7 @@ import ( "context" "testing" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/stretchr/testify/require" @@ -45,8 +46,8 @@ func TestInit(t *testing.T) { "Global config name and email", []string{}, map[string]string{ - env.UserNameKey: "Bill Billerson", - env.UserEmailKey: "bigbillieb@fake.horse", + config.UserNameKey: "Bill Billerson", + config.UserEmailKey: "bigbillieb@fake.horse", }, true, }, @@ -80,8 +81,8 @@ func TestInit(t *testing.T) { if test.ExpectSuccess { require.True(t, dEnv.HasDoltDir(), "- .dolt dir should exist after initialization") - testLocalConfigValue(t, dEnv, test, usernameParamName, env.UserNameKey) - testLocalConfigValue(t, dEnv, test, emailParamName, env.UserEmailKey) + testLocalConfigValue(t, dEnv, test, usernameParamName, config.UserNameKey) + testLocalConfigValue(t, dEnv, test, emailParamName, config.UserEmailKey) } else { require.False(t, dEnv.HasDoltDir(), "- dolt directory shouldn't exist after failure to initialize") diff --git a/go/cmd/dolt/commands/login.go b/go/cmd/dolt/commands/login.go index 584d774174..952cd09469 100644 --- a/go/cmd/dolt/commands/login.go +++ b/go/cmd/dolt/commands/login.go @@ -21,6 +21,7 @@ import ( "strconv" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/skratchdot/open-golang/open" "google.golang.org/grpc" @@ -81,7 +82,7 @@ func (cmd LoginCmd) Docs() *cli.CommandDocumentation { func (cmd LoginCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithMaxArgs(cmd.Name(), 1) - ap.SupportsString(authEndpointParam, "e", "hostname:port", fmt.Sprintf("Specify the endpoint used to authenticate this client. Must be used with --%s OR set in the configuration file as `%s`", loginURLParam, env.AddCredsUrlKey)) + ap.SupportsString(authEndpointParam, "e", "hostname:port", fmt.Sprintf("Specify the endpoint used to authenticate this client. Must be used with --%s OR set in the configuration file as `%s`", loginURLParam, config.AddCredsUrlKey)) ap.SupportsString(loginURLParam, "url", "url", "Specify the login url where the browser will add credentials.") ap.SupportsFlag(insecureParam, "i", "If set, makes insecure connection to remote authentication server") ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"creds", "A specific credential to use for login. If omitted, new credentials will be generated."}) @@ -100,7 +101,7 @@ func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, apr := cli.ParseArgsOrDie(ap, args, help) // use config values over defaults, flag values over config values - loginUrl := dEnv.Config.GetStringOrDefault(env.AddCredsUrlKey, env.DefaultLoginUrl) + loginUrl := dEnv.Config.GetStringOrDefault(config.AddCredsUrlKey, env.DefaultLoginUrl) loginUrl = apr.GetValueOrDefault(loginURLParam, loginUrl) var authHost string @@ -114,8 +115,8 @@ func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, } authEndpoint = fmt.Sprintf("%s:%s", authHost, authPort) } else { - authHost = dEnv.Config.GetStringOrDefault(env.RemotesApiHostKey, env.DefaultRemotesApiHost) - authPort = dEnv.Config.GetStringOrDefault(env.RemotesApiHostPortKey, env.DefaultRemotesApiPort) + authHost = dEnv.Config.GetStringOrDefault(config.RemotesApiHostKey, env.DefaultRemotesApiHost) + authPort = dEnv.Config.GetStringOrDefault(config.RemotesApiHostPortKey, env.DefaultRemotesApiPort) authEndpoint = fmt.Sprintf("%s:%s", authHost, authPort) } @@ -128,10 +129,10 @@ func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, var err error if !insecure { - insecureStr := dEnv.Config.GetStringOrDefault(env.DoltLabInsecureKey, "false") + insecureStr := dEnv.Config.GetStringOrDefault(config.DoltLabInsecureKey, "false") insecure, err = strconv.ParseBool(insecureStr) if err != nil { - HandleVErrAndExitCode(errhand.BuildDError(fmt.Sprintf("The config value of '%s' is '%s' which is not a valid true/false value", env.DoltLabInsecureKey, insecureStr)).Build(), usage) + HandleVErrAndExitCode(errhand.BuildDError(fmt.Sprintf("The config value of '%s' is '%s' which is not a valid true/false value", config.DoltLabInsecureKey, insecureStr)).Build(), usage) } } @@ -269,9 +270,9 @@ func updateConfig(dEnv *env.DoltEnv, whoAmI *remotesapi.WhoAmIResponse, dCreds c panic("global config not found. Should create it here if this is a thing.") } - gcfg.SetStrings(map[string]string{env.UserCreds: dCreds.KeyIDBase32Str()}) + gcfg.SetStrings(map[string]string{config.UserCreds: dCreds.KeyIDBase32Str()}) - userUpdates := map[string]string{env.UserNameKey: whoAmI.DisplayName, env.UserEmailKey: whoAmI.EmailAddress} + userUpdates := map[string]string{config.UserNameKey: whoAmI.DisplayName, config.UserEmailKey: whoAmI.EmailAddress} lcfg, hasLCfg := dEnv.Config.GetConfig(env.LocalConfig) if hasLCfg { diff --git a/go/cmd/dolt/commands/merge.go b/go/cmd/dolt/commands/merge.go index ac535ffa30..8403acec56 100644 --- a/go/cmd/dolt/commands/merge.go +++ b/go/cmd/dolt/commands/merge.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -174,8 +175,8 @@ func validateDoltMergeArgs(apr *argparser.ArgParseResults, usage cli.UsagePrinte if !cli.CheckUserNameAndEmail(cliCtx.Config()) { bdr := errhand.BuildDError("Could not determine name and/or email.") bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", env.UserNameKey) - bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey) + bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey) + bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey) return HandleVErrAndExitCode(bdr.Build(), usage) } diff --git a/go/cmd/dolt/commands/pull.go b/go/cmd/dolt/commands/pull.go index aa43263b1d..ae51345df2 100644 --- a/go/cmd/dolt/commands/pull.go +++ b/go/cmd/dolt/commands/pull.go @@ -21,6 +21,7 @@ import ( "strings" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/gocraft/dbr/v2" "github.com/gocraft/dbr/v2/dialect" @@ -93,8 +94,8 @@ func (cmd PullCmd) Exec(ctx context.Context, commandStr string, args []string, d if !cli.CheckUserNameAndEmail(cliCtx.Config()) { bdr := errhand.BuildDError("Could not determine name and/or email.") bdr.AddDetails("Log into DoltHub: dolt login") - bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", env.UserNameKey) - bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", env.UserEmailKey) + bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey) + bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey) return HandleVErrAndExitCode(bdr.Build(), usage) } diff --git a/go/cmd/dolt/commands/remote_test.go b/go/cmd/dolt/commands/remote_test.go index 638146619d..ef5c6d3ae7 100644 --- a/go/cmd/dolt/commands/remote_test.go +++ b/go/cmd/dolt/commands/remote_test.go @@ -59,7 +59,7 @@ func TestGetAbsRemoteUrl(t *testing.T) { { "ts/emp", config.NewMapConfig(map[string]string{ - env.RemotesApiHostKey: "host.dom", + config.RemotesApiHostKey: "host.dom", }), "https://host.dom/ts/emp", "https", @@ -75,7 +75,7 @@ func TestGetAbsRemoteUrl(t *testing.T) { { "https://test.org:443/ts/emp", config.NewMapConfig(map[string]string{ - env.RemotesApiHostKey: "host.dom", + config.RemotesApiHostKey: "host.dom", }), "https://test.org:443/ts/emp", "https", @@ -84,7 +84,7 @@ func TestGetAbsRemoteUrl(t *testing.T) { { "localhost/ts/emp", config.NewMapConfig(map[string]string{ - env.RemotesApiHostKey: "host.dom", + config.RemotesApiHostKey: "host.dom", }), "https://localhost/ts/emp", "https", diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index f269a87d59..9004c329aa 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -25,6 +25,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" ) @@ -81,7 +82,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{ShortDesc: sendMetricsShortDesc}, ap)) apr := cli.ParseArgsOrDie(ap, args, help) - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) if err != nil { diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index de1de6785e..cb90c49f49 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -575,7 +576,7 @@ type heartbeatService struct { } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) if err != nil || disabled { return &heartbeatService{} // will be defunct on Run() diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index d3b5251589..27146394ab 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -749,7 +749,7 @@ func seedGlobalRand() { // 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. // This is mostly used for testing. func emitUsageEvents(dEnv *env.DoltEnv, homeDir string, args []string) { - metricsDisabled := dEnv.Config.GetStringOrDefault(env.MetricsDisabled, "false") + metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) if err != nil || disabled { return diff --git a/go/libraries/doltcore/dtestutils/environment.go b/go/libraries/doltcore/dtestutils/environment.go index 740ec0e20e..c2d1eddf86 100644 --- a/go/libraries/doltcore/dtestutils/environment.go +++ b/go/libraries/doltcore/dtestutils/environment.go @@ -21,6 +21,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/filesys" "github.com/dolthub/dolt/go/store/types" ) @@ -100,8 +101,8 @@ func createTestEnvWithNameAndFilesystem(envName string, fs filesys.Filesys, home dEnv := env.Load(context.Background(), homeDirFunc, fs, urlStr, "test") cfg, _ := dEnv.Config.GetConfig(env.GlobalConfig) cfg.SetStrings(map[string]string{ - env.UserNameKey: name, - env.UserEmailKey: email, + config.UserNameKey: name, + config.UserEmailKey: email, }) err := dEnv.InitRepo(context.Background(), types.Format_Default, name, email, env.DefaultInitBranch) diff --git a/go/libraries/doltcore/dtestutils/testcommands/multienv.go b/go/libraries/doltcore/dtestutils/testcommands/multienv.go index ecb6ba4db1..3273cc7f20 100644 --- a/go/libraries/doltcore/dtestutils/testcommands/multienv.go +++ b/go/libraries/doltcore/dtestutils/testcommands/multienv.go @@ -22,6 +22,7 @@ import ( cmd "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dprocedures" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" @@ -121,8 +122,8 @@ func (mr *MultiRepoTestSetup) NewDB(dbName string) { } cfg, _ := dEnv.Config.GetConfig(env.GlobalConfig) cfg.SetStrings(map[string]string{ - env.UserNameKey: name, - env.UserEmailKey: email, + config.UserNameKey: name, + config.UserEmailKey: email, }) err = dEnv.InitRepo(context.Background(), types.Format_Default, name, email, defaultBranch) if err != nil { diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index f24abd5142..d69b11e3e4 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -22,6 +22,7 @@ import ( "sort" "sync" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dustin/go-humanize" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -267,8 +268,8 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // InitEmptyClonedRepo inits an empty, newly cloned repo. This would be unnecessary if we properly initialized the // storage for a repository when we created it on dolthub. If we do that, this code can be removed. func InitEmptyClonedRepo(ctx context.Context, dEnv *env.DoltEnv) error { - name := dEnv.Config.GetStringOrDefault(env.UserNameKey, "") - email := dEnv.Config.GetStringOrDefault(env.UserEmailKey, "") + name := dEnv.Config.GetStringOrDefault(config.UserNameKey, "") + email := dEnv.Config.GetStringOrDefault(config.UserEmailKey, "") initBranch := env.GetDefaultInitBranch(dEnv.Config) if name == "" { diff --git a/go/libraries/doltcore/env/config.go b/go/libraries/doltcore/env/config.go index cea50a439a..82fa344714 100644 --- a/go/libraries/doltcore/env/config.go +++ b/go/libraries/doltcore/env/config.go @@ -22,7 +22,6 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/filesys" - "github.com/dolthub/dolt/go/libraries/utils/set" "github.com/dolthub/dolt/go/store/datas" ) @@ -30,33 +29,10 @@ const ( localConfigName = "local" globalConfigName = "global" - UserEmailKey = "user.email" - UserNameKey = "user.name" - // should be able to have remote specific creds? - UserCreds = "user.creds" - DoltEditor = "core.editor" - - InitBranchName = "init.defaultbranch" - - RemotesApiHostKey = "remotes.default_host" - RemotesApiHostPortKey = "remotes.default_port" - - AddCredsUrlKey = "creds.add_url" - DoltLabInsecureKey = "doltlab.insecure" - - MetricsDisabled = "metrics.disabled" - MetricsHost = "metrics.host" - MetricsPort = "metrics.port" - MetricsInsecure = "metrics.insecure" - - PushAutoSetupRemote = "push.autosetupremote" ) -var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) -var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) - // ConfigScope is an enum representing the elements that make up the ConfigHierarchy type ConfigScope int @@ -206,7 +182,7 @@ func GetStringOrDefault(cfg config.ReadableConfig, key, defStr string) string { // GetNameAndEmail returns the name and email from the supplied config func GetNameAndEmail(cfg config.ReadableConfig) (string, string, error) { - name, err := cfg.GetString(UserNameKey) + name, err := cfg.GetString(config.UserNameKey) if err == config.ErrConfigParamNotFound { return "", "", datas.ErrNameNotConfigured @@ -214,7 +190,7 @@ func GetNameAndEmail(cfg config.ReadableConfig) (string, string, error) { return "", "", err } - email, err := cfg.GetString(UserEmailKey) + email, err := cfg.GetString(config.UserEmailKey) if err == config.ErrConfigParamNotFound { return "", "", datas.ErrEmailNotConfigured @@ -258,8 +234,8 @@ const ( ) var DefaultFailsafeConfig = map[string]string{ - UserEmailKey: DefaultEmail, - UserNameKey: DefaultName, + config.UserEmailKey: DefaultEmail, + config.UserNameKey: DefaultName, } func (w writeableLocalDoltCliConfig) SetStrings(updates map[string]string) error { diff --git a/go/libraries/doltcore/env/config_test.go b/go/libraries/doltcore/env/config_test.go index dc363fca1b..0ab85b6042 100644 --- a/go/libraries/doltcore/env/config_test.go +++ b/go/libraries/doltcore/env/config_test.go @@ -34,15 +34,15 @@ func TestConfig(t *testing.T) { lCfg, _ := dEnv.Config.GetConfig(LocalConfig) gCfg, _ := dEnv.Config.GetConfig(GlobalConfig) - lCfg.SetStrings(map[string]string{UserEmailKey: email, UserNameKey: "local_override"}) - gCfg.SetStrings(map[string]string{UserNameKey: name}) + lCfg.SetStrings(map[string]string{config.UserEmailKey: email, config.UserNameKey: "local_override"}) + gCfg.SetStrings(map[string]string{config.UserNameKey: name}) - assert.Equal(t, email, dEnv.Config.GetStringOrDefault(UserEmailKey, "no")) - assert.Equal(t, "local_override", dEnv.Config.GetStringOrDefault(UserNameKey, "no")) + assert.Equal(t, email, dEnv.Config.GetStringOrDefault(config.UserEmailKey, "no")) + assert.Equal(t, "local_override", dEnv.Config.GetStringOrDefault(config.UserNameKey, "no")) assert.Equal(t, "yes", dEnv.Config.GetStringOrDefault("bad_key", "yes")) - assert.Equal(t, email, dEnv.Config.IfEmptyUseConfig("", UserEmailKey)) - assert.Equal(t, "not empty", dEnv.Config.IfEmptyUseConfig("not empty", UserEmailKey)) + assert.Equal(t, email, dEnv.Config.IfEmptyUseConfig("", config.UserEmailKey)) + assert.Equal(t, "not empty", dEnv.Config.IfEmptyUseConfig("not empty", config.UserEmailKey)) assert.Equal(t, "", dEnv.Config.IfEmptyUseConfig("", "missing")) @@ -54,17 +54,17 @@ func TestFailsafes(t *testing.T) { dEnv, _ := createTestEnv(true, true) lCfg, _ := dEnv.Config.GetConfig(LocalConfig) - require.NoError(t, lCfg.Unset([]string{UserNameKey})) + require.NoError(t, lCfg.Unset([]string{config.UserNameKey})) dEnv.Config.SetFailsafes(DefaultFailsafeConfig) - assert.Equal(t, DefaultEmail, dEnv.Config.GetStringOrDefault(UserEmailKey, "none")) - assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, DefaultEmail, dEnv.Config.GetStringOrDefault(config.UserEmailKey, "none")) + assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(config.UserNameKey, "none")) - dEnv.Config.SetFailsafes(map[string]string{UserEmailKey: "new", "abc": "def"}) + dEnv.Config.SetFailsafes(map[string]string{config.UserEmailKey: "new", "abc": "def"}) - assert.Equal(t, "new", dEnv.Config.GetStringOrDefault(UserEmailKey, "none")) - assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, "new", dEnv.Config.GetStringOrDefault(config.UserEmailKey, "none")) + assert.Equal(t, DefaultName, dEnv.Config.GetStringOrDefault(config.UserNameKey, "none")) assert.Equal(t, "def", dEnv.Config.GetStringOrDefault("abc", "none")) } @@ -75,23 +75,23 @@ func TestWritableDoltConfig(t *testing.T) { gCfg, _ := dEnv.Config.GetConfig(GlobalConfig) lCfg, _ := dEnv.Config.GetConfig(LocalConfig) - require.NoError(t, gCfg.SetStrings(map[string]string{UserNameKey: name})) - require.NoError(t, lCfg.SetStrings(map[string]string{UserNameKey: localName})) + require.NoError(t, gCfg.SetStrings(map[string]string{config.UserNameKey: name})) + require.NoError(t, lCfg.SetStrings(map[string]string{config.UserNameKey: localName})) cfg := dEnv.Config.WriteableConfig() - assert.Equal(t, localName, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, localName, cfg.GetStringOrDefault(config.UserNameKey, "none")) require.NoError(t, cfg.SetStrings(map[string]string{"test": "abc"})) - require.NoError(t, cfg.Unset([]string{UserNameKey})) + require.NoError(t, cfg.Unset([]string{config.UserNameKey})) - assert.Equal(t, name, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, name, cfg.GetStringOrDefault(config.UserNameKey, "none")) assert.Equal(t, "abc", cfg.GetStringOrDefault("test", "none")) - _, err := lCfg.GetString(UserNameKey) + _, err := lCfg.GetString(config.UserNameKey) assert.Equal(t, config.ErrConfigParamNotFound, err) - assert.Equal(t, name, gCfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, name, gCfg.GetStringOrDefault(config.UserNameKey, "none")) _, err = gCfg.GetString("test") assert.Equal(t, config.ErrConfigParamNotFound, err) } @@ -102,22 +102,22 @@ func TestWritableDoltConfigNoLocal(t *testing.T) { newName := "Willy" gCfg, _ := dEnv.Config.GetConfig(GlobalConfig) - require.NoError(t, gCfg.SetStrings(map[string]string{UserNameKey: name, "test": "abc"})) + require.NoError(t, gCfg.SetStrings(map[string]string{config.UserNameKey: name, "test": "abc"})) cfg := dEnv.Config.WriteableConfig() - assert.Equal(t, name, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, name, cfg.GetStringOrDefault(config.UserNameKey, "none")) assert.Equal(t, "abc", cfg.GetStringOrDefault("test", "none")) - require.NoError(t, cfg.SetStrings(map[string]string{UserNameKey: newName})) + require.NoError(t, cfg.SetStrings(map[string]string{config.UserNameKey: newName})) require.NoError(t, cfg.Unset([]string{"test"})) - assert.Equal(t, newName, cfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, newName, cfg.GetStringOrDefault(config.UserNameKey, "none")) _, err := cfg.GetString("test") assert.Equal(t, config.ErrConfigParamNotFound, err) - assert.Equal(t, newName, gCfg.GetStringOrDefault(UserNameKey, "none")) + assert.Equal(t, newName, gCfg.GetStringOrDefault(config.UserNameKey, "none")) _, err = gCfg.GetString("test") assert.Equal(t, config.ErrConfigParamNotFound, err) diff --git a/go/libraries/doltcore/env/environment.go b/go/libraries/doltcore/env/environment.go index 209d95d6f6..9f7b7ba20a 100644 --- a/go/libraries/doltcore/env/environment.go +++ b/go/libraries/doltcore/env/environment.go @@ -46,9 +46,6 @@ const ( DefaultLoginUrl = "https://dolthub.com/settings/credentials" - DefaultMetricsHost = "eventsapi.dolthub.com" - DefaultMetricsPort = "443" - DefaultRemotesApiHost = "doltremoteapi.dolthub.com" DefaultRemotesApiPort = "443" @@ -202,7 +199,7 @@ func Load(ctx context.Context, hdp HomeDirProvider, fs filesys.Filesys, urlStr s } func GetDefaultInitBranch(cfg config.ReadableConfig) string { - return GetStringOrDefault(cfg, InitBranchName, DefaultInitBranch) + return GetStringOrDefault(cfg, config.InitBranchName, DefaultInitBranch) } // Valid returns whether this environment has been properly initialized. This is useful because although every command @@ -814,8 +811,8 @@ func (dEnv *DoltEnv) workingSetMeta() *datas.WorkingSetMeta { func (dEnv *DoltEnv) NewWorkingSetMeta(message string) *datas.WorkingSetMeta { return &datas.WorkingSetMeta{ - Name: dEnv.Config.GetStringOrDefault(UserNameKey, ""), - Email: dEnv.Config.GetStringOrDefault(UserEmailKey, ""), + Name: dEnv.Config.GetStringOrDefault(config.UserNameKey, ""), + Email: dEnv.Config.GetStringOrDefault(config.UserEmailKey, ""), Timestamp: uint64(time.Now().Unix()), Description: message, } @@ -826,7 +823,7 @@ func (dEnv *DoltEnv) CredsDir() (string, error) { } func (dEnv *DoltEnv) UserDoltCreds() (creds.DoltCreds, bool, error) { - kid, err := dEnv.Config.GetString(UserCreds) + kid, err := dEnv.Config.GetString(config.UserCreds) if err == nil && kid != "" { dir, err := dEnv.CredsDir() diff --git a/go/libraries/doltcore/env/multi_repo_env_test.go b/go/libraries/doltcore/env/multi_repo_env_test.go index c5d2674093..b7fbeff7d5 100644 --- a/go/libraries/doltcore/env/multi_repo_env_test.go +++ b/go/libraries/doltcore/env/multi_repo_env_test.go @@ -20,6 +20,7 @@ import ( "path/filepath" "testing" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -103,8 +104,8 @@ func initRepoWithRelativePath(t *testing.T, envPath string, hdp HomeDirProvider) dEnv := Load(context.Background(), hdp, fs, urlStr, "test") cfg, _ := dEnv.Config.GetConfig(GlobalConfig) cfg.SetStrings(map[string]string{ - UserNameKey: name, - UserEmailKey: email, + config.UserNameKey: name, + config.UserEmailKey: email, }) err = dEnv.InitRepo(context.Background(), types.Format_Default, name, email, DefaultInitBranch) diff --git a/go/libraries/doltcore/env/remotes.go b/go/libraries/doltcore/env/remotes.go index 61505b5263..089957041f 100644 --- a/go/libraries/doltcore/env/remotes.go +++ b/go/libraries/doltcore/env/remotes.go @@ -661,7 +661,7 @@ func GetAbsRemoteUrl(fs filesys2.Filesys, cfg config.ReadableConfig, urlArg stri return dbfactory.HTTPSScheme, "https://" + urlArg, nil } - hostName, err := cfg.GetString(RemotesApiHostKey) + hostName, err := cfg.GetString(config.RemotesApiHostKey) if err != nil { if err != config.ErrConfigParamNotFound { diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go index a332771e42..d67626dc1d 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go @@ -18,6 +18,7 @@ import ( "fmt" "strconv" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" @@ -70,7 +71,7 @@ func doDoltPush(ctx *sql.Context, args []string) (int, string, error) { return cmdFailure, "", err } - autoSetUpRemote := loadConfig(ctx).GetStringOrDefault(env.PushAutoSetupRemote, "false") + autoSetUpRemote := loadConfig(ctx).GetStringOrDefault(config.PushAutoSetupRemote, "false") pushAutoSetUpRemote, err := strconv.ParseBool(autoSetUpRemote) if err != nil { return cmdFailure, "", err diff --git a/go/libraries/doltcore/sqle/dsess/session.go b/go/libraries/doltcore/sqle/dsess/session.go index 1a71596919..442dd7a0bb 100644 --- a/go/libraries/doltcore/sqle/dsess/session.go +++ b/go/libraries/doltcore/sqle/dsess/session.go @@ -95,8 +95,8 @@ func NewDoltSession( conf config.ReadWriteConfig, branchController *branch_control.Controller, ) (*DoltSession, error) { - username := conf.GetStringOrDefault(env.UserNameKey, "") - email := conf.GetStringOrDefault(env.UserEmailKey, "") + username := conf.GetStringOrDefault(config.UserNameKey, "") + email := conf.GetStringOrDefault(config.UserEmailKey, "") globals := config.NewPrefixConfig(conf, env.SqlServerGlobalsPrefix) sess := &DoltSession{ diff --git a/go/libraries/doltcore/sqle/testutil.go b/go/libraries/doltcore/sqle/testutil.go index 99ec7ca619..42823f6a39 100644 --- a/go/libraries/doltcore/sqle/testutil.go +++ b/go/libraries/doltcore/sqle/testutil.go @@ -399,8 +399,8 @@ func CreateTestEnvWithName(envName string) *env.DoltEnv { dEnv := env.Load(context.Background(), homeDirFunc, fs, doltdb.InMemDoltDB+envName, "test") cfg, _ := dEnv.Config.GetConfig(env.GlobalConfig) cfg.SetStrings(map[string]string{ - env.UserNameKey: name, - env.UserEmailKey: email, + config2.UserNameKey: name, + config2.UserEmailKey: email, }) err := dEnv.InitRepo(context.Background(), types.Format_Default, name, email, env.DefaultInitBranch) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 4352294d8e..f2c5576e8c 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -25,7 +25,6 @@ import ( "time" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" - "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" @@ -46,6 +45,9 @@ const ( EmitterTypeFile = "file" ) +const DefaultMetricsHost = "eventsapi.dolthub.com" +const DefaultMetricsPort = "443" + // Emitter is an interface used for processing a batch of events type Emitter interface { // LogEvents takes a batch of events and processes them @@ -214,9 +216,9 @@ func GRPCEmitterForConfig(pro EmitterConfigProvider) *GrpcEmitter { // GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { - host := pro.GetConfig().GetStringOrDefault(env.MetricsHost, env.DefaultMetricsHost) - portStr := pro.GetConfig().GetStringOrDefault(env.MetricsPort, env.DefaultMetricsPort) - insecureStr := pro.GetConfig().GetStringOrDefault(env.MetricsInsecure, "false") + host := pro.GetConfig().GetStringOrDefault(config.MetricsHost, DefaultMetricsHost) + portStr := pro.GetConfig().GetStringOrDefault(config.MetricsPort, DefaultMetricsPort) + insecureStr := pro.GetConfig().GetStringOrDefault(config.MetricsInsecure, "false") port, err := strconv.ParseUint(portStr, 10, 16) if err != nil { diff --git a/go/libraries/utils/config/keys.go b/go/libraries/utils/config/keys.go new file mode 100755 index 0000000000..a83da32bf8 --- /dev/null +++ b/go/libraries/utils/config/keys.go @@ -0,0 +1,51 @@ +// Copyright 2023 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "github.com/dolthub/dolt/go/libraries/utils/set" +) + +const UserEmailKey = "user.email" + +const UserNameKey = "user.name" + +const UserCreds = "user.creds" + +const DoltEditor = "core.editor" + +const InitBranchName = "init.defaultbranch" + +const RemotesApiHostKey = "remotes.default_host" + +const RemotesApiHostPortKey = "remotes.default_port" + +const AddCredsUrlKey = "creds.add_url" + +const DoltLabInsecureKey = "doltlab.insecure" + +const MetricsDisabled = "metrics.disabled" + +const MetricsHost = "metrics.host" + +const MetricsPort = "metrics.port" + +const MetricsInsecure = "metrics.insecure" + +const PushAutoSetupRemote = "push.autosetupremote" + +var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) +var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) + From 3a81a6f9a7b3bdfbad2ff4ebd174dc28f104b696 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:20:57 -0800 Subject: [PATCH 20/63] Unified flushing --- go/cmd/dolt/commands/send_metrics.go | 31 ++++++------ go/cmd/dolt/commands/sqlserver/server.go | 32 ++++++------ go/libraries/events/emitter.go | 42 ++++++++++++---- go/libraries/events/event_flush.go | 63 ++++++++++++++++++++++++ go/libraries/utils/config/keys.go | 8 --- 5 files changed, 128 insertions(+), 48 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 9004c329aa..b045e46abd 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -32,8 +32,8 @@ import ( // SendMetricsCommand is the command used for sending metrics const ( SendMetricsCommand = "send-metrics" - outputFlag = "output" - sendMetricsShortDesc = "Send metrics to the events server or print them to stdout" + EventsOutputFormat = "output-format" + sendMetricsShortDesc = "Send metrics to the events server (default), or log them in another way" ) type SendMetricsCmd struct{} @@ -65,7 +65,12 @@ func (cmd SendMetricsCmd) Docs() *cli.CommandDocumentation { func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithMaxArgs(cmd.Name(), 0) - ap.SupportsFlag(outputFlag, "o", "Flush events to stdout.") + ap.SupportsString( + EventsOutputFormat, + "r", + "output-format", + "Format of the events output. Valid values are null, writer, grpc, and file.", + ) return ap } @@ -103,9 +108,9 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st if err != nil { return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - - outputToStdio := apr.Contains(outputFlag) - err = FlushLoggedEvents(ctx, dEnv, userHomeDir, outputToStdio) + + output := apr.GetValueOrDefault(EventsOutputFormat, "grpc") + err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) if err != nil { if err == events.ErrFileLocked { @@ -122,15 +127,13 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st } // FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter -func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputToStdio bool) error { - var flusher events.Flusher - if outputToStdio { - flusher = events.NewIOFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir) - } else { - grpcEmitter := events.GRPCEmitterForConfig(dEnv) - flusher = events.NewGrpcEventFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, grpcEmitter) +func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputType string) error { + emitter, err := events.NewEmitter(outputType, dEnv) + if err != nil { + return err } - + + flusher := events.NewFileFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, emitter) return flusher.Flush(ctx) } diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index cb90c49f49..037b3993af 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "net/http" + "os" "runtime" "strconv" "strings" @@ -37,14 +38,12 @@ import ( "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sirupsen/logrus" - "google.golang.org/grpc" goerrors "gopkg.in/src-d/go-errors.v1" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/commands" "github.com/dolthub/dolt/go/cmd/dolt/commands/engine" eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" - "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/remotesrv" "github.com/dolthub/dolt/go/libraries/doltcore/sqle" @@ -572,7 +571,7 @@ func Serve( // heartbeatService is a service that sends a heartbeat event to the metrics server once a day type heartbeatService struct { version string - cfg dbfactory.GRPCRemoteConfig + eventEmitter events.Emitter } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { @@ -582,16 +581,25 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { return &heartbeatService{} // will be defunct on Run() } - cfg, _ := events.GRPCEventRemoteConfig(dEnv) - return &heartbeatService{version: version, cfg: cfg} + emitterType, ok := os.LookupEnv(events.EmitterTypeEnvVar) + if !ok { + emitterType = events.EmitterTypeGrpc + } + + emitter, err := events.NewEmitter(emitterType, dEnv) + if err != nil { + return &heartbeatService{} // will be defunct on Run() + } + + return &heartbeatService{version: version, eventEmitter: emitter} } func (h *heartbeatService) Init(ctx context.Context) error { return nil } func (h *heartbeatService) Stop() error { return nil } func (h *heartbeatService) Run(ctx context.Context) { - // Faulty config settings or disabled metrics can cause us to not have a valid endpoint - if h.cfg.Endpoint == "" { + // Faulty config settings or disabled metrics can cause us to not have a valid event emitter + if h.eventEmitter == nil { return } @@ -603,14 +611,8 @@ func (h *heartbeatService) Run(ctx context.Context) { case <-ctx.Done(): return case <-ticker.C: - conn, err := grpc.Dial(h.cfg.Endpoint, h.cfg.DialOptions...) - if err != nil { - continue - } - - eventEmitter := events.NewGrpcEmitter(conn) t := events.NowTimestamp() - err = eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ + err := h.eventEmitter.LogEvents(h.version, []*eventsapi.ClientEvent{ { Id: uuid.New().String(), StartTime: t, @@ -622,8 +624,6 @@ func (h *heartbeatService) Run(ctx context.Context) { if err != nil { logrus.Debugf("failed to send heartbeat event: %v", err) } - - _ = conn.Close() } } } diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index f2c5576e8c..886c894188 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -27,6 +27,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/config" + "github.com/fatih/color" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -37,6 +38,8 @@ import ( var Application = eventsapi.AppID_APP_DOLT +// EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below +// to change how event emission occurs. This is useful for testing and in some environments. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" const ( EmitterTypeNull = "null" @@ -50,8 +53,10 @@ const DefaultMetricsPort = "443" // Emitter is an interface used for processing a batch of events type Emitter interface { - // LogEvents takes a batch of events and processes them + // LogEvents emits a batch of events LogEvents(version string, evts []*eventsapi.ClientEvent) error + // LogEventsRequest emits a batch of events wrapped in a request object, with other metadata + LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error } // EmitterConfigProvider is an interface used to get the configuration to create an emitter @@ -69,6 +74,10 @@ func (ne NullEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) e return nil } +func (ne NullEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + return nil +} + // WriterEmitter is an emitter that writes the text encoding of the events to it's writer type WriterEmitter struct { // Wr the writer to log events to @@ -105,7 +114,12 @@ func (we WriterEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return nil } -// GrpcEmitter sends events to a GRPC service implementing the eventsapi +func (we WriterEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + _, err := fmt.Fprintf(color.Output, "%+v\n", req) + return err +} + + // GrpcEmitter sends events to a GRPC service implementing the eventsapi type GrpcEmitter struct { client eventsapi.ClientEventsServiceClient } @@ -143,6 +157,10 @@ func (em *GrpcEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return err } +func (em *GrpcEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + return em.SendLogEventsRequest(ctx, req) +} + // SendLogEventsRequest sends a request using the grpc client func (em *GrpcEmitter) SendLogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { _, err := em.client.LogEvents(ctx, req) @@ -173,15 +191,19 @@ func (fe *FileEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) return nil } -// NewEmitter returns an emitter for the given configuration provider, keyed off the DOLT_EVENTS_EMITTER environment -// variable. If it's not set, defaults to a file-based emitter. -func NewEmitter(pro EmitterConfigProvider) (Emitter, error) { - envVarType, ok := os.LookupEnv(EmitterTypeEnvVar) - if !ok { - envVarType = EmitterTypeFile +func (fe *FileEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + // TODO: we are losing some information here, like the machine id + if err := fe.fbp.WriteEvents(req.Version, req.Events); err != nil { + return err } - switch envVarType { + return nil +} + +// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, +// defaults to a file-based emitter. +func NewEmitter(emitterType string, pro EmitterConfigProvider) (Emitter, error) { + switch emitterType { case EmitterTypeNull: return NullEmitter{}, nil case EmitterTypeWriter: @@ -195,7 +217,7 @@ func NewEmitter(pro EmitterConfigProvider) (Emitter, error) { } return NewFileEmitter(homeDir, dbfactory.DoltDir), nil default: - return nil, fmt.Errorf("unknown emitter type: %s", envVarType) + return nil, fmt.Errorf("unknown emitter type: %s", emitterType) } } diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index dace99c86c..c8db25c599 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -47,6 +47,69 @@ type Flusher interface { Flush(ctx context.Context) error } +type FileFlusher struct { + emitter Emitter + fbp *FileBackedProc +} + +func NewFileFlusher(fs filesys.Filesys, userHomeDir string, doltDir string, emitter Emitter) *FileFlusher { + fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) + + if exists := fbp.EventsDirExists(); !exists { + panic(ErrEventsDataDir) + } + + return &FileFlusher{emitter: emitter, fbp: fbp} +} + +func (f FileFlusher) Flush(ctx context.Context) error { + fs := f.fbp.GetFileSys() + + evtsDir := f.fbp.GetEventsDirPath() + + err := lockAndFlush(ctx, fs, evtsDir, f.fbp.LockPath, f.flush) + if err != nil { + return err + } + + return nil +} + +// flush has the function signature of the flushCb type +// and sends events data to the events server +func (f FileFlusher) flush(ctx context.Context, path string) error { + fs := f.fbp.GetFileSys() + + data, err := fs.ReadFile(path) + if err != nil { + return err + } + + isFileValid, err := f.fbp.CheckingFunc(data, path) + + if isFileValid && err == nil { + req := &eventsapi.LogEventsRequest{} + + if err := proto.Unmarshal(data, req); err != nil { + return err + } + + if err := f.emitter.LogEventsRequest(ctx, req); err != nil { + return err + } + + if err := fs.DeleteFile(path); err != nil { + return err + } + + return nil + } + + return errInvalidFile +} + +var _ Flusher = &FileFlusher{} + // lockAndFlush locks the given lockPath and passes the flushCB to the filesys' Iter method func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string, fcb flushCB) error { fsLock := filesys.CreateFilesysLock(fs, lockPath) diff --git a/go/libraries/utils/config/keys.go b/go/libraries/utils/config/keys.go index a83da32bf8..57f80654c6 100755 --- a/go/libraries/utils/config/keys.go +++ b/go/libraries/utils/config/keys.go @@ -14,10 +14,6 @@ package config -import ( - "github.com/dolthub/dolt/go/libraries/utils/set" -) - const UserEmailKey = "user.email" const UserNameKey = "user.name" @@ -45,7 +41,3 @@ const MetricsPort = "metrics.port" const MetricsInsecure = "metrics.insecure" const PushAutoSetupRemote = "push.autosetupremote" - -var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) -var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) - From f1b1521bed9d22fc191dab260d01c87c90933f68 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:21:57 -0800 Subject: [PATCH 21/63] Removed unused flusher impls --- go/libraries/events/event_flush.go | 126 +---------------------------- 1 file changed, 2 insertions(+), 124 deletions(-) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index c8db25c599..82961c5afa 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -17,10 +17,8 @@ package events import ( "context" "errors" - "fmt" "github.com/dolthub/fslock" - "github.com/fatih/color" "google.golang.org/protobuf/proto" eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" @@ -124,7 +122,7 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP }() if err != nil { - if err == fslock.ErrLocked { + if errors.Is(err, fslock.ErrLocked) { return ErrFileLocked } return err @@ -148,124 +146,4 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP } return nil -} - -// GrpcEventFlusher parses dolt event logs sends the events to the events server -type GrpcEventFlusher struct { - em *GrpcEmitter - fbp *FileBackedProc -} - -// NewGrpcEventFlusher creates a new GrpcEventFlusher -func NewGrpcEventFlusher(fs filesys.Filesys, userHomeDir string, doltDir string, grpcEmitter *GrpcEmitter) *GrpcEventFlusher { - fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) - - if exists := fbp.EventsDirExists(); !exists { - panic(ErrEventsDataDir) - } - - return &GrpcEventFlusher{em: grpcEmitter, fbp: fbp} -} - -// flush has the function signature of the flushCb type -// and sends events data to the events server -func (egf *GrpcEventFlusher) flush(ctx context.Context, path string) error { - fs := egf.fbp.GetFileSys() - - data, err := fs.ReadFile(path) - if err != nil { - return err - } - - isFileValid, err := egf.fbp.CheckingFunc(data, path) - - if isFileValid && err == nil { - req := &eventsapi.LogEventsRequest{} - - if err := proto.Unmarshal(data, req); err != nil { - return err - } - - if err := egf.em.SendLogEventsRequest(ctx, req); err != nil { - return err - } - - if err := fs.DeleteFile(path); err != nil { - return err - } - - return nil - } - - return errInvalidFile -} - -// Flush satisfies the Flusher interface and calls this Flusher's flush method on each events file -func (egf *GrpcEventFlusher) Flush(ctx context.Context) error { - fs := egf.fbp.GetFileSys() - - evtsDir := egf.fbp.GetEventsDirPath() - - err := lockAndFlush(ctx, fs, evtsDir, egf.fbp.LockPath, egf.flush) - if err != nil { - return err - } - - return nil -} - -// IOFlusher parses event files and writes them to stdout -type IOFlusher struct { - fbp *FileBackedProc -} - -// NewIOFlusher creates a new IOFlusher -func NewIOFlusher(fs filesys.Filesys, userHomeDir string, doltDir string) *IOFlusher { - fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) - - if exists := fbp.EventsDirExists(); !exists { - panic(ErrEventsDataDir) - } - - return &IOFlusher{fbp: fbp} -} - -// flush has the function signature of the flushCb type -// and writes data to stdout -func (iof *IOFlusher) flush(ctx context.Context, path string) error { - fs := iof.fbp.GetFileSys() - - data, err := fs.ReadFile(path) - if err != nil { - return err - } - - req := &eventsapi.LogEventsRequest{} - - if err := proto.Unmarshal(data, req); err != nil { - return err - } - - // needed for bats test - fmt.Fprintf(color.Output, "%+v\n", req) - - if err := fs.DeleteFile(path); err != nil { - return err - } - - return nil -} - -// Flush satisfies the Flusher interface and calls this Flusher's flush method on each events file -func (iof *IOFlusher) Flush(ctx context.Context) error { - fs := iof.fbp.GetFileSys() - - evtsDir := iof.fbp.GetEventsDirPath() - - err := lockAndFlush(ctx, fs, evtsDir, iof.fbp.LockPath, iof.flush) - if err != nil { - return err - } - - return nil -} +} \ No newline at end of file From 736941a72c204079e46184db0afc86f98f0f4898 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:37:17 -0800 Subject: [PATCH 22/63] Renamed a const --- go/cmd/dolt/commands/send_metrics.go | 4 ++-- go/libraries/events/emitter.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index b045e46abd..a5e7c075fa 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -69,7 +69,7 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { EventsOutputFormat, "r", "output-format", - "Format of the events output. Valid values are null, writer, grpc, and file.", + "Format of the events output. Valid values are null, stdio, grpc, and file.", ) return ap } @@ -109,7 +109,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - output := apr.GetValueOrDefault(EventsOutputFormat, "grpc") + output := apr.GetValueOrDefault(EventsOutputFormat, events.EmitterTypeGrpc) err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) if err != nil { diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 886c894188..c66ae25021 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -43,7 +43,7 @@ var Application = eventsapi.AppID_APP_DOLT const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" const ( EmitterTypeNull = "null" - EmitterTypeWriter = "writer" + EmitterTypeStdout = "stdout" EmitterTypeGrpc = "grpc" EmitterTypeFile = "file" ) @@ -206,7 +206,7 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (Emitter, error) switch emitterType { case EmitterTypeNull: return NullEmitter{}, nil - case EmitterTypeWriter: + case EmitterTypeStdout: return WriterEmitter{Wr: os.Stdout}, nil case EmitterTypeGrpc: return GRPCEmitterForConfig(pro), nil From f9e6922900d21f1ba309e6054293a05c1f16a4b7 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 15:42:02 -0800 Subject: [PATCH 23/63] Configurable heartbeat interval --- go/cmd/dolt/commands/send_metrics.go | 1 - go/cmd/dolt/commands/sqlserver/server.go | 22 ++++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index a5e7c075fa..0432ff37c4 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -75,7 +75,6 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { } // Exec is the implementation of the command that flushes the events to the grpc service -// Exec executes the command func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { if dEnv.DoltDB != nil { // see go/cmd/dolt/dolt.go:interceptSendMetrics() cli.PrintErrln("expected DoltEnv without DoltDB") diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 037b3993af..c6ef70ef03 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -61,6 +61,9 @@ const ( ApiSqleContextKey = "__sqle_context__" ) +// sqlServerHeartbeatIntervalEnvVar is the duration between heartbeats sent to the remote server, used for testing +const sqlServerHeartbeatIntervalEnvVar = "DOLT_SQL_SERVER_HEARTBEAT_INTERVAL" + // ExternalDisableUsers is called by implementing applications to disable users. This is not used by Dolt itself, // but will break compatibility with implementing applications that do not yet support users. var ExternalDisableUsers bool = false @@ -572,6 +575,7 @@ func Serve( type heartbeatService struct { version string eventEmitter events.Emitter + interval time.Duration } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { @@ -591,7 +595,21 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { return &heartbeatService{} // will be defunct on Run() } - return &heartbeatService{version: version, eventEmitter: emitter} + interval, ok := os.LookupEnv(sqlServerHeartbeatIntervalEnvVar) + if !ok { + interval = "24h" + } + + duration, err := time.ParseDuration(interval) + if err != nil { + return nil + } + + return &heartbeatService{ + version: version, + eventEmitter: emitter, + interval: duration, + } } func (h *heartbeatService) Init(ctx context.Context) error { return nil } @@ -603,7 +621,7 @@ func (h *heartbeatService) Run(ctx context.Context) { return } - ticker := time.NewTicker(24 * time.Hour) + ticker := time.NewTicker(h.interval) defer ticker.Stop() for { From a7b31a373637214f8872b7662dd125c493379ca6 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 16:21:59 -0800 Subject: [PATCH 24/63] End to end tests of metrics logging --- integration-tests/bats/send-metrics.bats | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index 312d2f05f4..d561e25ec0 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -17,9 +17,9 @@ teardown() { cp -a $BATS_TEST_DIRNAME/helper/testEvents/* $BATS_TMPDIR/config-$$/.dolt/eventsData/ # kick off two child processes, one should lock the other out of the events dir - dolt send-metrics -output >file1.txt & + dolt send-metrics --output-format stdout >file1.txt & pid1=$! - dolt send-metrics -output >file2.txt & + dolt send-metrics --output-format stdout >file2.txt & pid2=$! # wait for processes to finish @@ -66,3 +66,28 @@ teardown() { echo this block should not fire return 1 } + +@test "send-metrics: test event logging" { + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" + DOLT_DISABLE_EVENT_FLUSH=true dolt ls + DOLT_DISABLE_EVENT_FLUSH=true dolt status + + # output all the metrics data to stdout for examination + run dolt send-metrics --output-format stdout + [ "$status" -eq 0 ] + [ "${#lines[@]}" -eq 4 ] + + # output is random-ordered, so we have to search line in it + sql_count=$(echo "$output" | grep -o "type:SQL" | wc -l) + ls_count=$(echo "$output" | grep -o "type:LS" | wc -l) + status_count=$(echo "$output" | grep -o "type:STATUS" | wc -l) + [ "$sql_count" -eq 2 ] + [ "$ls_count" -eq 1 ] + [ "$status_count" -eq 1 ] + + # send metrics should be empty after this, since it deletes all old metrics + run dolt send-metrics --output-format stdout + [ "$status" -eq 0 ] + [ "$output" == "" ] +} From 41637d5078962baaf29551efed2b30360a1168f7 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 16:22:48 -0800 Subject: [PATCH 25/63] Moved emitter constructor logic out of events packge, where it causes a cycle --- go/cmd/dolt/commands/send_metrics.go | 74 ++++++++++++++++++++++- go/cmd/dolt/commands/sqlserver/server.go | 12 ++-- go/cmd/dolt/commands/status.go | 6 ++ go/libraries/events/emitter.go | 75 +----------------------- 4 files changed, 86 insertions(+), 81 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 0432ff37c4..46fcaae340 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -16,6 +16,8 @@ package commands import ( "context" + "fmt" + "os" "strconv" "time" @@ -23,10 +25,12 @@ import ( "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" + "google.golang.org/grpc" ) // SendMetricsCommand is the command used for sending metrics @@ -127,7 +131,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st // FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir string, outputType string) error { - emitter, err := events.NewEmitter(outputType, dEnv) + emitter, err := NewEmitter(outputType, dEnv) if err != nil { return err } @@ -136,3 +140,71 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin return flusher.Flush(ctx) } +// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, +// defaults to a file-based emitter. +func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, error) { + switch emitterType { + case events.EmitterTypeNull: + return events.NullEmitter{}, nil + case events.EmitterTypeStdout: + return events.WriterEmitter{Wr: os.Stdout}, nil + case events.EmitterTypeGrpc: + return GRPCEmitterForConfig(pro), nil + case events.EmitterTypeFile: + homeDir, err := pro.GetUserHomeDir() + if err != nil { + return nil, err + } + return events.NewFileEmitter(homeDir, dbfactory.DoltDir), nil + default: + return nil, fmt.Errorf("unknown emitter type: %s", emitterType) + } +} + +// GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot +// provide one +func GRPCEmitterForConfig(pro EmitterConfigProvider) *events.GrpcEmitter { + cfg, err := GRPCEventRemoteConfig(pro) + if err != nil { + return nil + } + + conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) + if err != nil { + return nil + } + return events.NewGrpcEmitter(conn) +} + +// GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider +func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { + host := pro.GetConfig().GetStringOrDefault(config.MetricsHost, events.DefaultMetricsHost) + portStr := pro.GetConfig().GetStringOrDefault(config.MetricsPort, events.DefaultMetricsPort) + insecureStr := pro.GetConfig().GetStringOrDefault(config.MetricsInsecure, "false") + + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + insecure, _ := strconv.ParseBool(insecureStr) + + hostAndPort := fmt.Sprintf("%s:%d", host, port) + cfg, err := pro.GetGRPCDialParams(grpcendpoint.Config{ + Endpoint: hostAndPort, + Insecure: insecure, + }) + if err != nil { + return dbfactory.GRPCRemoteConfig{}, nil + } + + return cfg, nil +} + +// EmitterConfigProvider is an interface used to get the configuration to create an emitter +type EmitterConfigProvider interface { + GetGRPCDialParams(config grpcendpoint.Config) (dbfactory.GRPCRemoteConfig, error) + GetConfig() config.ReadableConfig + GetUserHomeDir() (string, error) +} + diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index c6ef70ef03..384491065b 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -590,11 +590,6 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { emitterType = events.EmitterTypeGrpc } - emitter, err := events.NewEmitter(emitterType, dEnv) - if err != nil { - return &heartbeatService{} // will be defunct on Run() - } - interval, ok := os.LookupEnv(sqlServerHeartbeatIntervalEnvVar) if !ok { interval = "24h" @@ -602,7 +597,12 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { duration, err := time.ParseDuration(interval) if err != nil { - return nil + return &heartbeatService{} // will be defunct on Run() + } + + emitter, err := commands.NewEmitter(emitterType, dEnv) + if err != nil { + return &heartbeatService{} // will be defunct on Run() } return &heartbeatService{ diff --git a/go/cmd/dolt/commands/status.go b/go/cmd/dolt/commands/status.go index cc87953b29..850cd4fc79 100644 --- a/go/cmd/dolt/commands/status.go +++ b/go/cmd/dolt/commands/status.go @@ -19,6 +19,7 @@ import ( "fmt" "strings" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" "github.com/fatih/color" @@ -72,6 +73,7 @@ func (cmd StatusCmd) RequiresRepo() bool { } var _ cli.RepoNotRequiredCommand = StatusCmd{} +var _ cli.EventMonitoredCommand = StatusCmd{} // Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command func (cmd StatusCmd) Name() string { @@ -94,6 +96,10 @@ func (cmd StatusCmd) ArgParser() *argparser.ArgParser { return ap } +func (cmd StatusCmd) EventType() eventsapi.ClientEventType { + return eventsapi.ClientEventType_STATUS +} + // Exec executes the command func (cmd StatusCmd) Exec(ctx context.Context, commandStr string, args []string, _ *env.DoltEnv, cliCtx cli.CliContext) int { // parse arguments diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index c66ae25021..7bc56d15a6 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -18,15 +18,10 @@ import ( "context" "fmt" "io" - "os" "runtime" - "strconv" "strings" "time" - "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" - "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -59,13 +54,6 @@ type Emitter interface { LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error } -// EmitterConfigProvider is an interface used to get the configuration to create an emitter -type EmitterConfigProvider interface { - GetGRPCDialParams(config grpcendpoint.Config) (dbfactory.GRPCRemoteConfig, error) - GetConfig() config.ReadableConfig - GetUserHomeDir() (string, error) -} - // NullEmitter is an emitter that drops events type NullEmitter struct{} @@ -198,65 +186,4 @@ func (fe *FileEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogE } return nil -} - -// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, -// defaults to a file-based emitter. -func NewEmitter(emitterType string, pro EmitterConfigProvider) (Emitter, error) { - switch emitterType { - case EmitterTypeNull: - return NullEmitter{}, nil - case EmitterTypeStdout: - return WriterEmitter{Wr: os.Stdout}, nil - case EmitterTypeGrpc: - return GRPCEmitterForConfig(pro), nil - case EmitterTypeFile: - homeDir, err := pro.GetUserHomeDir() - if err != nil { - return nil, err - } - return NewFileEmitter(homeDir, dbfactory.DoltDir), nil - default: - return nil, fmt.Errorf("unknown emitter type: %s", emitterType) - } -} - -// GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot -// provide one -func GRPCEmitterForConfig(pro EmitterConfigProvider) *GrpcEmitter { - cfg, err := GRPCEventRemoteConfig(pro) - if err != nil { - return nil - } - - conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) - if err != nil { - return nil - } - return NewGrpcEmitter(conn) -} - -// GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider -func GRPCEventRemoteConfig(pro EmitterConfigProvider) (dbfactory.GRPCRemoteConfig, error) { - host := pro.GetConfig().GetStringOrDefault(config.MetricsHost, DefaultMetricsHost) - portStr := pro.GetConfig().GetStringOrDefault(config.MetricsPort, DefaultMetricsPort) - insecureStr := pro.GetConfig().GetStringOrDefault(config.MetricsInsecure, "false") - - port, err := strconv.ParseUint(portStr, 10, 16) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - - insecure, _ := strconv.ParseBool(insecureStr) - - hostAndPort := fmt.Sprintf("%s:%d", host, port) - cfg, err := pro.GetGRPCDialParams(grpcendpoint.Config{ - Endpoint: hostAndPort, - Insecure: insecure, - }) - if err != nil { - return dbfactory.GRPCRemoteConfig{}, nil - } - - return cfg, nil -} +} \ No newline at end of file From b207b1bc0394b5424b2b1ee8a61b7bdf8251b672 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Mon, 4 Dec 2023 17:03:24 -0800 Subject: [PATCH 26/63] Smoke test for faulty GRPC config, fixed broken error handling in the case of a bad GRPC client --- go/cmd/dolt/commands/send_metrics.go | 52 ++++++++++++------------ go/libraries/events/event_flush.go | 31 +++++++------- integration-tests/bats/send-metrics.bats | 29 +++++++++++++ 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 46fcaae340..e00857c4a6 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -94,7 +94,6 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st disabled, err := strconv.ParseBool(metricsDisabled) if err != nil { - // log.Print(err) return 1 } @@ -103,30 +102,28 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st return 0 } - if !disabled { - ctx, cancel := context.WithTimeout(ctx, time.Minute) - defer cancel() + ctx, cancel := context.WithTimeout(ctx, time.Minute) + defer cancel() - userHomeDir, err := dEnv.GetUserHomeDir() - if err != nil { - return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) - } - - output := apr.GetValueOrDefault(EventsOutputFormat, events.EmitterTypeGrpc) - err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) - - if err != nil { - if err == events.ErrFileLocked { - return 2 - } - - return 1 - } - - return 0 + userHomeDir, err := dEnv.GetUserHomeDir() + if err != nil { + return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - return 1 + output := apr.GetValueOrDefault(EventsOutputFormat, events.EmitterTypeGrpc) + err = FlushLoggedEvents(ctx, dEnv, userHomeDir, output) + + if err != nil { + cli.PrintErrf("Error flushing events: %s\n", err.Error()) + + if err == events.ErrFileLocked { + return 2 + } + + return 1 + } + + return 0 } // FlushLoggedEvents flushes any logged events in the directory given to an appropriate event emitter @@ -149,7 +146,7 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, case events.EmitterTypeStdout: return events.WriterEmitter{Wr: os.Stdout}, nil case events.EmitterTypeGrpc: - return GRPCEmitterForConfig(pro), nil + return GRPCEmitterForConfig(pro) case events.EmitterTypeFile: homeDir, err := pro.GetUserHomeDir() if err != nil { @@ -163,17 +160,18 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, // GRPCEmitterForConfig returns an event emitter for the given environment, or nil if the environment cannot // provide one -func GRPCEmitterForConfig(pro EmitterConfigProvider) *events.GrpcEmitter { +func GRPCEmitterForConfig(pro EmitterConfigProvider) (*events.GrpcEmitter, error) { cfg, err := GRPCEventRemoteConfig(pro) if err != nil { - return nil + return nil, err } conn, err := grpc.Dial(cfg.Endpoint, cfg.DialOptions...) if err != nil { - return nil + return nil, err } - return events.NewGrpcEmitter(conn) + + return events.NewGrpcEmitter(conn), nil } // GRPCEventRemoteConfig returns a GRPCRemoteConfig for the given configuration provider diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index 82961c5afa..e6d0cbcb3a 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -128,22 +128,25 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP return err } - if isUnlocked && err == nil { - err := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { - if err := fcb(ctx, path); err != nil { - // log.Print(err) - return false - } - - return false - }) - - if err != nil { - return err - } - + if !isUnlocked { return nil } + var returnErr error + iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { + if err := fcb(ctx, path); err != nil { + returnErr = err + return true + } + + return false + }) + + if iterErr != nil { + return iterErr + } else if returnErr != nil { + return returnErr + } + return nil } \ No newline at end of file diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index d561e25ec0..1c8cdb53c0 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -91,3 +91,32 @@ teardown() { [ "$status" -eq 0 ] [ "$output" == "" ] } + +@test "send-metrics: grpc smoke test" { + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" + DOLT_DISABLE_EVENT_FLUSH=true dolt ls + DOLT_DISABLE_EVENT_FLUSH=true dolt status + + # output all the metrics data to stdout for examination + dolt config --global --add metrics.host "fake.server" + run dolt send-metrics + [ "$status" -eq 1 ] + [[ "$output" =~ "Error flushing events" ]] || false + [[ "$output" =~ "fake.server" ]] || false +} + +# TODO: we need a local metrics server here that we can spin up to verify the send actually works +@test "send-metrics: sql-server heartbeat" { + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" + DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" + DOLT_DISABLE_EVENT_FLUSH=true dolt ls + DOLT_DISABLE_EVENT_FLUSH=true dolt status + + # output all the metrics data to stdout for examination + dolt config --global --add metrics.host "fake.server" + dolt send-metrics + [ "$status" -eq 1 ] + [[ "$output" =~ "Error flushing events" ]] || false + [[ "$output" =~ "fake.server" ]] || false +} From 6b54e53586a059d6cea6fca315ae1613d365c61a Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Tue, 5 Dec 2023 09:53:02 -0800 Subject: [PATCH 27/63] simplify single-branch logic --- go/libraries/doltcore/env/actions/clone.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index e0cac4b902..b1c3c6e183 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -215,7 +215,7 @@ func CloneRemote(ctx context.Context, srcDB *doltdb.DoltDB, remoteName, branch s // create remote refs corresponding to each of them. We delete all of // the local branches except for the one corresponding to |branch|. for _, br := range branches { - if !singleBranch || (singleBranch && br.GetPath() == branch) { + if !singleBranch || br.GetPath() == branch { cs, _ := doltdb.NewCommitSpec(br.GetPath()) cm, err := dEnv.DoltDB.Resolve(ctx, cs, nil) if err != nil { From 7271e56ce80dff3205cc380b1de47af26c3c00fa Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 10:03:10 -0800 Subject: [PATCH 28/63] heartbeat tests --- integration-tests/bats/send-metrics.bats | 36 ++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index 1c8cdb53c0..b10fe2a66e 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -92,6 +92,8 @@ teardown() { [ "$output" == "" ] } +# TODO: we need a local metrics server here that we can spin up to verify the send actually works +# end-to-end @test "send-metrics: grpc smoke test" { DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" @@ -106,17 +108,29 @@ teardown() { [[ "$output" =~ "fake.server" ]] || false } -# TODO: we need a local metrics server here that we can spin up to verify the send actually works @test "send-metrics: sql-server heartbeat" { - DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "create table t1 (a int primary key, b int)" - DOLT_DISABLE_EVENT_FLUSH=true dolt sql -q "insert into t1 values (1, 2)" - DOLT_DISABLE_EVENT_FLUSH=true dolt ls - DOLT_DISABLE_EVENT_FLUSH=true dolt status - # output all the metrics data to stdout for examination - dolt config --global --add metrics.host "fake.server" - dolt send-metrics - [ "$status" -eq 1 ] - [[ "$output" =~ "Error flushing events" ]] || false - [[ "$output" =~ "fake.server" ]] || false + DOLT_EVENTS_EMITTER=stdout DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server > heartbeats.out 2>&1 & + server_pid=$! + sleep 5 + kill $server_pid + + wc=`grep SQL_SERVER_HEARTBEAT heartbeats.out | wc -l` + [ $wc -gt 0 ] +} + +# TODO: we need a local metrics server here that we can spin up to verify the send actually works +# end-to-end +@test "send-metrics: sql-server grpc heartbeat smoketest" { + dolt config --global --add metrics.host "fake.server" + DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server -l debug > heartbeats.out 2>&1 & + server_pid=$! + sleep 5 + kill $server_pid + + wc=`grep 'failed to send heartbeat event' heartbeats.out | wc -l` + [ $wc -gt 0 ] + + wc=`grep 'fake.server' heartbeats.out | wc -l` + [ $wc -gt 0 ] } From 8f8c186aaff38b3fe95ff8208ead43c17b28c907 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 10:23:25 -0800 Subject: [PATCH 29/63] bug fix --- go/libraries/events/event_flush.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index e6d0cbcb3a..d8f5daa34d 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -135,6 +135,10 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP var returnErr error iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { if err := fcb(ctx, path); err != nil { + if errors.Is(err, errInvalidFile) { + // ignore invalid files found in the events directory + return false + } returnErr = err return true } From 13d51ae1aefc00344ffb3c565e4d20627aa3883e Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:13:52 -0800 Subject: [PATCH 30/63] fixed test --- integration-tests/bats/send-metrics.bats | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/integration-tests/bats/send-metrics.bats b/integration-tests/bats/send-metrics.bats index b10fe2a66e..90019f2b9d 100644 --- a/integration-tests/bats/send-metrics.bats +++ b/integration-tests/bats/send-metrics.bats @@ -110,11 +110,13 @@ teardown() { @test "send-metrics: sql-server heartbeat" { # output all the metrics data to stdout for examination - DOLT_EVENTS_EMITTER=stdout DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server > heartbeats.out 2>&1 & + DOLT_EVENTS_EMITTER=logger DOLT_SQL_SERVER_HEARTBEAT_INTERVAL=1s dolt sql-server -l debug > heartbeats.out 2>&1 & server_pid=$! sleep 5 kill $server_pid + cat heartbeats.out + wc=`grep SQL_SERVER_HEARTBEAT heartbeats.out | wc -l` [ $wc -gt 0 ] } From 0d78a4ddc21438fd395a7d207c89ef42128680d4 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:14:08 -0800 Subject: [PATCH 31/63] Added a logger emitter --- go/cmd/dolt/commands/send_metrics.go | 3 ++ go/libraries/events/emitter.go | 63 +++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index e00857c4a6..666d6a0173 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -30,6 +30,7 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" + "github.com/sirupsen/logrus" "google.golang.org/grpc" ) @@ -153,6 +154,8 @@ func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, return nil, err } return events.NewFileEmitter(homeDir, dbfactory.DoltDir), nil + case events.EmitterTypeLogger: + return events.NewLoggerEmitter(logrus.DebugLevel), nil default: return nil, fmt.Errorf("unknown emitter type: %s", emitterType) } diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 7bc56d15a6..6d8c1ccad9 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -23,6 +23,7 @@ import ( "time" "github.com/fatih/color" + "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/prototext" @@ -34,13 +35,14 @@ import ( var Application = eventsapi.AppID_APP_DOLT // EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below -// to change how event emission occurs. This is useful for testing and in some environments. +// to change how event emission occurs. This is useful for the send-metrics command, and in some environments. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" const ( EmitterTypeNull = "null" EmitterTypeStdout = "stdout" EmitterTypeGrpc = "grpc" EmitterTypeFile = "file" + EmitterTypeLogger = "logger" ) const DefaultMetricsHost = "eventsapi.dolthub.com" @@ -186,4 +188,61 @@ func (fe *FileEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogE } return nil -} \ No newline at end of file +} + +type LoggerEmitter struct { + logLevel logrus.Level +} + +func (l LoggerEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) error { + sb := &strings.Builder{} + wr := WriterEmitter{Wr: sb} + err := wr.LogEvents(version, evts) + if err != nil { + return err + } + + eventString := sb.String() + return l.logEventString(eventString) +} + +func (l LoggerEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { + sb := &strings.Builder{} + wr := WriterEmitter{Wr: sb} + err := wr.LogEventsRequest(ctx, req) + if err != nil { + return err + } + + eventString := sb.String() + return l.logEventString(eventString) +} + +func (l LoggerEmitter) logEventString(eventString string) error { + switch l.logLevel { + case logrus.DebugLevel: + logrus.Debug(eventString) + case logrus.ErrorLevel: + logrus.Error(eventString) + case logrus.FatalLevel: + logrus.Fatal(eventString) + case logrus.InfoLevel: + logrus.Info(eventString) + case logrus.PanicLevel: + logrus.Panic(eventString) + case logrus.TraceLevel: + logrus.Trace(eventString) + case logrus.WarnLevel: + logrus.Warn(eventString) + default: + return fmt.Errorf("unknown log level %v", l.logLevel) + } + return nil +} + +func NewLoggerEmitter(level logrus.Level) *LoggerEmitter { + return &LoggerEmitter{ + logLevel: level, + } +} + From 07be50d655f8d4cffab0372f4c4225775e4ebd90 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:18:01 -0800 Subject: [PATCH 32/63] Fix up docs --- go/cmd/dolt/commands/send_metrics.go | 4 ++-- go/libraries/events/emitter.go | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 666d6a0173..550662cb22 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -38,7 +38,7 @@ import ( const ( SendMetricsCommand = "send-metrics" EventsOutputFormat = "output-format" - sendMetricsShortDesc = "Send metrics to the events server (default), or log them in another way" + sendMetricsShortDesc = "Send usage metrics to the events server (default), or log them in another way" ) type SendMetricsCmd struct{} @@ -74,7 +74,7 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { EventsOutputFormat, "r", "output-format", - "Format of the events output. Valid values are null, stdio, grpc, and file.", + "Format of the events output. Valid values are null, stdout, grpc, file, logger. Defaults to grpc.", ) return ap } diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 6d8c1ccad9..7f2176a6a2 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -35,14 +35,16 @@ import ( var Application = eventsapi.AppID_APP_DOLT // EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below -// to change how event emission occurs. This is useful for the send-metrics command, and in some environments. +// to change how event emission occurs. Currently only used for sql-server heartbeat events. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" + +// Types of emitters. These strings are accepted by the --output-format flag for the send-metrics command. const ( - EmitterTypeNull = "null" - EmitterTypeStdout = "stdout" - EmitterTypeGrpc = "grpc" - EmitterTypeFile = "file" - EmitterTypeLogger = "logger" + EmitterTypeNull = "null" // no output + EmitterTypeStdout = "stdout" // output to stdout, used in testing + EmitterTypeGrpc = "grpc" // output to a grpc server, the default for send-metrics + EmitterTypeFile = "file" // output to a file, used to log events during normal execution + EmitterTypeLogger = "logger" // output to a logger, used in testing ) const DefaultMetricsHost = "eventsapi.dolthub.com" From 2e963ee8f92fbfcf56d35d9b6e4c888fcd86511c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 11:37:48 -0800 Subject: [PATCH 33/63] Fix test --- go/libraries/events/event_flush_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index d6c75054d2..d56800892d 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -52,7 +52,7 @@ func NewTestClient() *TestClient { type flushTester struct { Client *TestClient Fbp *FileBackedProc - Flusher *GrpcEventFlusher + Flusher *FileFlusher } func createFlushTester(fs filesys.Filesys, hdir string, ddir string) *flushTester { @@ -62,7 +62,7 @@ func createFlushTester(fs filesys.Filesys, hdir string, ddir string) *flushTeste fbp := NewFileBackedProc(fs, hdir, ddir, sn.Name, sn.Check) - gef := &GrpcEventFlusher{em: &GrpcEmitter{client}, fbp: fbp} + gef := &FileFlusher{emitter: &GrpcEmitter{client}, fbp: fbp} return &flushTester{Client: client, Fbp: fbp, Flusher: gef} } From 59632204cd1f6cb9bb73792d22cc91a998c4a913 Mon Sep 17 00:00:00 2001 From: zachmu Date: Tue, 5 Dec 2023 19:44:51 +0000 Subject: [PATCH 34/63] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/cmd/dolt/cli/command.go | 2 +- go/cmd/dolt/commands/commit.go | 2 +- go/cmd/dolt/commands/credcmds/check.go | 2 +- go/cmd/dolt/commands/credcmds/import.go | 2 +- go/cmd/dolt/commands/init.go | 2 +- go/cmd/dolt/commands/init_test.go | 2 +- go/cmd/dolt/commands/login.go | 2 +- go/cmd/dolt/commands/merge.go | 2 +- go/cmd/dolt/commands/pull.go | 2 +- go/cmd/dolt/commands/send_metrics.go | 20 +++++++++---------- go/cmd/dolt/commands/sqlserver/server.go | 14 ++++++------- go/cmd/dolt/commands/status.go | 2 +- go/cmd/dolt/dolt.go | 11 +++++----- .../eventsapi/v1alpha1/event_constants.pb.go | 5 +++-- go/libraries/doltcore/env/actions/clone.go | 2 +- .../doltcore/env/multi_repo_env_test.go | 2 +- .../doltcore/sqle/dprocedures/dolt_push.go | 2 +- go/libraries/events/emitter.go | 11 +++++----- go/libraries/events/event_flush.go | 10 +++++----- 19 files changed, 49 insertions(+), 48 deletions(-) diff --git a/go/cmd/dolt/cli/command.go b/go/cmd/dolt/cli/command.go index 60bbab53fb..b07a5d8847 100644 --- a/go/cmd/dolt/cli/command.go +++ b/go/cmd/dolt/cli/command.go @@ -22,7 +22,6 @@ import ( "strings" "syscall" - config "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" @@ -30,6 +29,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" + config "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/nbs" "github.com/dolthub/dolt/go/store/types" ) diff --git a/go/cmd/dolt/commands/commit.go b/go/cmd/dolt/commands/commit.go index 372d6a8396..04589bb285 100644 --- a/go/cmd/dolt/commands/commit.go +++ b/go/cmd/dolt/commands/commit.go @@ -22,7 +22,6 @@ import ( "os" "strings" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -38,6 +37,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/editor" "github.com/dolthub/dolt/go/libraries/utils/iohelp" "github.com/dolthub/dolt/go/libraries/utils/set" diff --git a/go/cmd/dolt/commands/credcmds/check.go b/go/cmd/dolt/commands/credcmds/check.go index edb29fe30e..ce11cec726 100644 --- a/go/cmd/dolt/commands/credcmds/check.go +++ b/go/cmd/dolt/commands/credcmds/check.go @@ -19,7 +19,6 @@ import ( "fmt" "net" - "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -31,6 +30,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) var checkShortDesc = "Check authenticating with a credential keypair against a doltremoteapi." diff --git a/go/cmd/dolt/commands/credcmds/import.go b/go/cmd/dolt/commands/credcmds/import.go index 5c3251e651..d39c078b65 100644 --- a/go/cmd/dolt/commands/credcmds/import.go +++ b/go/cmd/dolt/commands/credcmds/import.go @@ -20,7 +20,6 @@ import ( "io" "os" - "github.com/dolthub/dolt/go/libraries/utils/config" "google.golang.org/grpc" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -33,6 +32,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) var importDocs = cli.CommandDocumentationContent{ diff --git a/go/cmd/dolt/commands/init.go b/go/cmd/dolt/commands/init.go index ea4c451c27..a5ef81bcfc 100644 --- a/go/cmd/dolt/commands/init.go +++ b/go/cmd/dolt/commands/init.go @@ -19,7 +19,6 @@ import ( "fmt" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/fatih/color" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -27,6 +26,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/dconfig" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/datas" "github.com/dolthub/dolt/go/store/types" ) diff --git a/go/cmd/dolt/commands/init_test.go b/go/cmd/dolt/commands/init_test.go index f0fba3f519..ab5a411d1e 100644 --- a/go/cmd/dolt/commands/init_test.go +++ b/go/cmd/dolt/commands/init_test.go @@ -18,13 +18,13 @@ import ( "context" "testing" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/stretchr/testify/require" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) type initTest struct { diff --git a/go/cmd/dolt/commands/login.go b/go/cmd/dolt/commands/login.go index 952cd09469..35ae1ac209 100644 --- a/go/cmd/dolt/commands/login.go +++ b/go/cmd/dolt/commands/login.go @@ -21,7 +21,6 @@ import ( "strconv" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/skratchdot/open-golang/open" "google.golang.org/grpc" @@ -34,6 +33,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/doltcore/grpcendpoint" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" ) const ( diff --git a/go/cmd/dolt/commands/merge.go b/go/cmd/dolt/commands/merge.go index 8403acec56..ad93fb17c5 100644 --- a/go/cmd/dolt/commands/merge.go +++ b/go/cmd/dolt/commands/merge.go @@ -23,7 +23,6 @@ import ( "strconv" "strings" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/fatih/color" "github.com/gocraft/dbr/v2" @@ -37,6 +36,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/merge" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/util/outputpager" ) diff --git a/go/cmd/dolt/commands/pull.go b/go/cmd/dolt/commands/pull.go index ae51345df2..9362f335e1 100644 --- a/go/cmd/dolt/commands/pull.go +++ b/go/cmd/dolt/commands/pull.go @@ -21,7 +21,6 @@ import ( "strings" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/gocraft/dbr/v2" "github.com/gocraft/dbr/v2/dialect" @@ -32,6 +31,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/util/outputpager" ) diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index 550662cb22..4cc2a6243d 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -21,6 +21,10 @@ import ( "strconv" "time" + "github.com/fatih/color" + "github.com/sirupsen/logrus" + "google.golang.org/grpc" + "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" @@ -29,15 +33,12 @@ import ( "github.com/dolthub/dolt/go/libraries/events" "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/libraries/utils/config" - "github.com/fatih/color" - "github.com/sirupsen/logrus" - "google.golang.org/grpc" ) // SendMetricsCommand is the command used for sending metrics const ( SendMetricsCommand = "send-metrics" - EventsOutputFormat = "output-format" + EventsOutputFormat = "output-format" sendMetricsShortDesc = "Send usage metrics to the events server (default), or log them in another way" ) @@ -74,7 +75,7 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser { EventsOutputFormat, "r", "output-format", - "Format of the events output. Valid values are null, stdout, grpc, file, logger. Defaults to grpc.", + "Format of the events output. Valid values are null, stdout, grpc, file, logger. Defaults to grpc.", ) return ap } @@ -120,7 +121,7 @@ func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []st if err == events.ErrFileLocked { return 2 } - + return 1 } @@ -133,12 +134,12 @@ func FlushLoggedEvents(ctx context.Context, dEnv *env.DoltEnv, userHomeDir strin if err != nil { return err } - + flusher := events.NewFileFlusher(dEnv.FS, userHomeDir, dbfactory.DoltDir, emitter) return flusher.Flush(ctx) } -// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, +// NewEmitter returns an emitter for the given configuration provider, of the type named. If an empty name is provided, // defaults to a file-based emitter. func NewEmitter(emitterType string, pro EmitterConfigProvider) (events.Emitter, error) { switch emitterType { @@ -173,7 +174,7 @@ func GRPCEmitterForConfig(pro EmitterConfigProvider) (*events.GrpcEmitter, error if err != nil { return nil, err } - + return events.NewGrpcEmitter(conn), nil } @@ -208,4 +209,3 @@ type EmitterConfigProvider interface { GetConfig() config.ReadableConfig GetUserHomeDir() (string, error) } - diff --git a/go/cmd/dolt/commands/sqlserver/server.go b/go/cmd/dolt/commands/sqlserver/server.go index 384491065b..c34a6cd9c1 100644 --- a/go/cmd/dolt/commands/sqlserver/server.go +++ b/go/cmd/dolt/commands/sqlserver/server.go @@ -27,7 +27,6 @@ import ( "strings" "time" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/server" "github.com/dolthub/go-mysql-server/sql" @@ -53,6 +52,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" "github.com/dolthub/dolt/go/libraries/doltcore/sqlserver" "github.com/dolthub/dolt/go/libraries/events" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/svcs" ) @@ -573,9 +573,9 @@ func Serve( // heartbeatService is a service that sends a heartbeat event to the metrics server once a day type heartbeatService struct { - version string + version string eventEmitter events.Emitter - interval time.Duration + interval time.Duration } func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { @@ -599,16 +599,16 @@ func newHeartbeatService(version string, dEnv *env.DoltEnv) *heartbeatService { if err != nil { return &heartbeatService{} // will be defunct on Run() } - + emitter, err := commands.NewEmitter(emitterType, dEnv) if err != nil { return &heartbeatService{} // will be defunct on Run() } - + return &heartbeatService{ - version: version, + version: version, eventEmitter: emitter, - interval: duration, + interval: duration, } } diff --git a/go/cmd/dolt/commands/status.go b/go/cmd/dolt/commands/status.go index 850cd4fc79..1747762c3a 100644 --- a/go/cmd/dolt/commands/status.go +++ b/go/cmd/dolt/commands/status.go @@ -19,13 +19,13 @@ import ( "fmt" "strings" - eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" "github.com/fatih/color" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" + eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/utils/argparser" diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 27146394ab..ddaadcd37f 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -210,6 +210,7 @@ Not all subcommands use these flags. If your command accepts these flags without ` const disableEventFlushEnvVar = "DOLT_DISABLE_EVENT_FLUSH" + var eventFlushDisabled = false func init() { @@ -219,7 +220,7 @@ func init() { dumpZshCommand.DoltCommand = doltCommand dfunctions.VersionString = Version if _, ok := os.LookupEnv(disableEventFlushEnvVar); ok { - eventFlushDisabled = true + eventFlushDisabled = true } } @@ -472,7 +473,7 @@ func runMain() int { cli.PrintErrln(color.RedString("Failure to parse arguments: %v", err)) return 1 } - + defer emitUsageEvents(dEnv, homeDir, args) if needsWriteAccess(subcommandName) { @@ -745,9 +746,9 @@ func seedGlobalRand() { // emitUsageEvents is called after a command is run to emit usage events and send them to metrics servers. // Two controls of this behavior are possible: -// 1. The config key |metrics.disabled|, when set to |true|, disables all metrics emission -// 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. -// This is mostly used for testing. +// 1. The config key |metrics.disabled|, when set to |true|, disables all metrics emission +// 2. The environment key |DOLT_DISABLE_EVENT_FLUSH| allows writing events to disk but not sending them to the server. +// This is mostly used for testing. func emitUsageEvents(dEnv *env.DoltEnv, homeDir string, args []string) { metricsDisabled := dEnv.Config.GetStringOrDefault(config.MetricsDisabled, "false") disabled, err := strconv.ParseBool(metricsDisabled) diff --git a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go index 8d23ad67a9..a180d1b5a3 100644 --- a/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go +++ b/go/gen/proto/dolt/services/eventsapi/v1alpha1/event_constants.pb.go @@ -23,10 +23,11 @@ package eventsapi import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/go/libraries/doltcore/env/actions/clone.go b/go/libraries/doltcore/env/actions/clone.go index d69b11e3e4..106aa5be08 100644 --- a/go/libraries/doltcore/env/actions/clone.go +++ b/go/libraries/doltcore/env/actions/clone.go @@ -22,7 +22,6 @@ import ( "sort" "sync" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dustin/go-humanize" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -30,6 +29,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/ref" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/filesys" "github.com/dolthub/dolt/go/libraries/utils/iohelp" "github.com/dolthub/dolt/go/libraries/utils/strhelp" diff --git a/go/libraries/doltcore/env/multi_repo_env_test.go b/go/libraries/doltcore/env/multi_repo_env_test.go index b7fbeff7d5..9a5b6bdb82 100644 --- a/go/libraries/doltcore/env/multi_repo_env_test.go +++ b/go/libraries/doltcore/env/multi_repo_env_test.go @@ -20,12 +20,12 @@ import ( "path/filepath" "testing" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/dconfig" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/libraries/utils/earl" "github.com/dolthub/dolt/go/libraries/utils/filesys" "github.com/dolthub/dolt/go/libraries/utils/test" diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go index d67626dc1d..309446de9b 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_push.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_push.go @@ -18,7 +18,6 @@ import ( "fmt" "strconv" - "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" @@ -28,6 +27,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" + "github.com/dolthub/dolt/go/libraries/utils/config" "github.com/dolthub/dolt/go/store/datas" ) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 7f2176a6a2..2eacaaca77 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -34,16 +34,16 @@ import ( var Application = eventsapi.AppID_APP_DOLT -// EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below +// EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below // to change how event emission occurs. Currently only used for sql-server heartbeat events. const EmitterTypeEnvVar = "DOLT_EVENTS_EMITTER" // Types of emitters. These strings are accepted by the --output-format flag for the send-metrics command. const ( - EmitterTypeNull = "null" // no output + EmitterTypeNull = "null" // no output EmitterTypeStdout = "stdout" // output to stdout, used in testing - EmitterTypeGrpc = "grpc" // output to a grpc server, the default for send-metrics - EmitterTypeFile = "file" // output to a file, used to log events during normal execution + EmitterTypeGrpc = "grpc" // output to a grpc server, the default for send-metrics + EmitterTypeFile = "file" // output to a file, used to log events during normal execution EmitterTypeLogger = "logger" // output to a logger, used in testing ) @@ -111,7 +111,7 @@ func (we WriterEmitter) LogEventsRequest(ctx context.Context, req *eventsapi.Log return err } - // GrpcEmitter sends events to a GRPC service implementing the eventsapi +// GrpcEmitter sends events to a GRPC service implementing the eventsapi type GrpcEmitter struct { client eventsapi.ClientEventsServiceClient } @@ -247,4 +247,3 @@ func NewLoggerEmitter(level logrus.Level) *LoggerEmitter { logLevel: level, } } - diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index d8f5daa34d..c427efc62d 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -47,12 +47,12 @@ type Flusher interface { type FileFlusher struct { emitter Emitter - fbp *FileBackedProc + fbp *FileBackedProc } func NewFileFlusher(fs filesys.Filesys, userHomeDir string, doltDir string, emitter Emitter) *FileFlusher { fbp := NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5) - + if exists := fbp.EventsDirExists(); !exists { panic(ErrEventsDataDir) } @@ -145,12 +145,12 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP return false }) - + if iterErr != nil { return iterErr } else if returnErr != nil { return returnErr } - + return nil -} \ No newline at end of file +} From 9d3d1ca3e0bf5406ad3dd230ca57fe0b56fb034a Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 12:25:54 -0800 Subject: [PATCH 35/63] Test fixes --- go/libraries/events/event_flush.go | 6 +- go/libraries/events/event_flush_test.go | 59 ++++++++++---------- go/libraries/events/file_backed_proc_test.go | 6 +- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index d8f5daa34d..f2fa3cd899 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -65,7 +65,7 @@ func (f FileFlusher) Flush(ctx context.Context) error { evtsDir := f.fbp.GetEventsDirPath() - err := lockAndFlush(ctx, fs, evtsDir, f.fbp.LockPath, f.flush) + err := f.lockAndFlush(ctx, fs, evtsDir, f.fbp.LockPath) if err != nil { return err } @@ -109,7 +109,7 @@ func (f FileFlusher) flush(ctx context.Context, path string) error { var _ Flusher = &FileFlusher{} // lockAndFlush locks the given lockPath and passes the flushCB to the filesys' Iter method -func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string, fcb flushCB) error { +func (f FileFlusher) lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string) error { fsLock := filesys.CreateFilesysLock(fs, lockPath) isUnlocked, err := fsLock.TryLock() @@ -134,7 +134,7 @@ func lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockP var returnErr error iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { - if err := fcb(ctx, path); err != nil { + if err := f.flush(ctx, path); err != nil { if errors.Is(err, errInvalidFile) { // ignore invalid files found in the events directory return false diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index d56800892d..bb98c7d455 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -86,46 +86,49 @@ func TestEventFlushing(t *testing.T) { }, } - filesystems := []string{"inMemFS", "local"} - + // filesystems := []string{"inMemFS", "local"} + filesystems := []string{"local"} + for _, fsName := range filesystems { - for _, test := range tests { + t.Run(fsName, func(t *testing.T) { + for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - ctx := context.Background() + t.Run(test.name, func(t *testing.T) { + ctx := context.Background() - var ft *flushTester + var ft *flushTester - if fsName == "inMemFS" { - fs := filesys.NewInMemFS([]string{tempEvtsDir}, nil, tempEvtsDir) + if fsName == "inMemFS" { + fs := filesys.NewInMemFS([]string{tempEvtsDir}, nil, tempEvtsDir) - ft = createFlushTester(fs, homeDir, doltTestDir) - } else { - fs := filesys.LocalFS + ft = createFlushTester(fs, homeDir, doltTestDir) + } else { + fs := filesys.LocalFS - path := filepath.Join(dPath, evtPath) - dDir := testLib.TestDir(path) + path := filepath.Join(dPath, evtPath) + dDir := testLib.TestDir(path) - ft = createFlushTester(fs, "", dDir) - } + ft = createFlushTester(fs, "", dDir) + } - ces := make([]*eventsapi.ClientEvent, 0) + ces := make([]*eventsapi.ClientEvent, 0) - for i := 0; i < test.numEvents; i++ { - ce := &eventsapi.ClientEvent{} - ces = append(ces, ce) - } + for i := 0; i < test.numEvents; i++ { + ce := &eventsapi.ClientEvent{} + ces = append(ces, ce) + } - assert.Equal(t, len(ces), test.numEvents) + assert.Equal(t, len(ces), test.numEvents) - err := ft.Fbp.WriteEvents(testVersion, ces) - assert.Equal(t, err, nil) + err := ft.Fbp.WriteEvents(testVersion, ces) + assert.Equal(t, err, nil) - err = ft.Flusher.Flush(ctx) + err = ft.Flusher.Flush(ctx) - assert.Equal(t, err, nil) - assert.Equal(t, len(ft.Client.CES), len(ces)) - }) - } + assert.NoError(t, err) + assert.Equal(t, len(ft.Client.CES), len(ces)) + }) + } + }) } } diff --git a/go/libraries/events/file_backed_proc_test.go b/go/libraries/events/file_backed_proc_test.go index fb1f9f5fcd..0deefb64b4 100644 --- a/go/libraries/events/file_backed_proc_test.go +++ b/go/libraries/events/file_backed_proc_test.go @@ -42,8 +42,10 @@ func (namer *SequentialNamer) Name(bytes []byte) string { } func (namer *SequentialNamer) Check(data []byte, path string) (bool, error) { - // todo - return true, nil + filename := filepath.Base(path) + ext := filepath.Ext(filename) + + return ext == evtDataExt, nil } func (namer *SequentialNamer) GetIdx() int { From e4389240b5756972ff2222c951b5986a4632ed12 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 12:41:17 -0800 Subject: [PATCH 36/63] Bug fix for windows lock file --- go/libraries/events/event_flush.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/go/libraries/events/event_flush.go b/go/libraries/events/event_flush.go index 8407153509..91cbdf0a4d 100644 --- a/go/libraries/events/event_flush.go +++ b/go/libraries/events/event_flush.go @@ -17,6 +17,7 @@ package events import ( "context" "errors" + "io/fs" "github.com/dolthub/fslock" "google.golang.org/protobuf/proto" @@ -109,8 +110,8 @@ func (f FileFlusher) flush(ctx context.Context, path string) error { var _ Flusher = &FileFlusher{} // lockAndFlush locks the given lockPath and passes the flushCB to the filesys' Iter method -func (f FileFlusher) lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPath string, lockPath string) error { - fsLock := filesys.CreateFilesysLock(fs, lockPath) +func (f FileFlusher) lockAndFlush(ctx context.Context, fsys filesys.Filesys, dirPath string, lockPath string) error { + fsLock := filesys.CreateFilesysLock(fsys, lockPath) isUnlocked, err := fsLock.TryLock() defer func() error { @@ -133,11 +134,15 @@ func (f FileFlusher) lockAndFlush(ctx context.Context, fs filesys.Filesys, dirPa } var returnErr error - iterErr := fs.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { + iterErr := fsys.Iter(dirPath, false, func(path string, size int64, isDir bool) (stop bool) { if err := f.flush(ctx, path); err != nil { if errors.Is(err, errInvalidFile) { // ignore invalid files found in the events directory return false + } else if _, isPathError := err.(*fs.PathError); isPathError { + // The lock file on windows has this issue, skip this file + // We can't use errors.Is because fs.PathError doesn't implement Is + return false } returnErr = err return true From d3cda14fe346e7dfc4b679ce77c1fbe383d97db4 Mon Sep 17 00:00:00 2001 From: zachmu Date: Tue, 5 Dec 2023 20:48:00 +0000 Subject: [PATCH 37/63] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/libraries/events/event_flush_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index bb98c7d455..bab36338cd 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -88,7 +88,7 @@ func TestEventFlushing(t *testing.T) { // filesystems := []string{"inMemFS", "local"} filesystems := []string{"local"} - + for _, fsName := range filesystems { t.Run(fsName, func(t *testing.T) { for _, test := range tests { From 8ae7445ef8e216aef9ee09e1a69c86ea208fc4da Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 12:48:49 -0800 Subject: [PATCH 38/63] Upgrade hadoop (older version now gone) --- .github/workflows/ci-bats-unix-remote.yaml | 6 +++--- .github/workflows/ci-bats-unix.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-bats-unix-remote.yaml b/.github/workflows/ci-bats-unix-remote.yaml index ee8a98dc06..7302c351bd 100644 --- a/.github/workflows/ci-bats-unix-remote.yaml +++ b/.github/workflows/ci-bats-unix-remote.yaml @@ -93,9 +93,9 @@ jobs: - name: Install Hadoop working-directory: ./.ci_bin run: | - curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz - tar xvf hadoop-3.3.4.tar.gz - echo "$(pwd)/hadoop-3.3.4/bin" >> $GITHUB_PATH + curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz + tar xvf hadoop-3.3.6.tar.gz + echo "$(pwd)/hadoop-3.3.6/bin" >> $GITHUB_PATH - name: Install parquet-cli id: parquet_cli working-directory: ./.ci_bin diff --git a/.github/workflows/ci-bats-unix.yaml b/.github/workflows/ci-bats-unix.yaml index 126b40a18d..e6db9efb50 100644 --- a/.github/workflows/ci-bats-unix.yaml +++ b/.github/workflows/ci-bats-unix.yaml @@ -93,9 +93,9 @@ jobs: - name: Install Hadoop working-directory: ./.ci_bin run: | - curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz - tar xvf hadoop-3.3.4.tar.gz - echo "$(pwd)/hadoop-3.3.4/bin" >> $GITHUB_PATH + curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz + tar xvf hadoop-3.3.6.tar.gz + echo "$(pwd)/hadoop-3.3.6/bin" >> $GITHUB_PATH - name: Install parquet-cli id: parquet_cli working-directory: ./.ci_bin From f54aa12850ba2b1cec289c0c28b3f041eb5de710 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Tue, 5 Dec 2023 13:56:24 -0800 Subject: [PATCH 39/63] Uncommented debug code --- go/libraries/events/event_flush_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/go/libraries/events/event_flush_test.go b/go/libraries/events/event_flush_test.go index bab36338cd..1798aba4db 100644 --- a/go/libraries/events/event_flush_test.go +++ b/go/libraries/events/event_flush_test.go @@ -86,8 +86,7 @@ func TestEventFlushing(t *testing.T) { }, } - // filesystems := []string{"inMemFS", "local"} - filesystems := []string{"local"} + filesystems := []string{"inMemFS", "local"} for _, fsName := range filesystems { t.Run(fsName, func(t *testing.T) { From 6c5c03dffe773a8428804478b3130d6269c01b30 Mon Sep 17 00:00:00 2001 From: Aaron Son Date: Tue, 5 Dec 2023 11:33:01 -0800 Subject: [PATCH 40/63] integration-tests/bats: Small bats tests improvements for the lambda runner. --- integration-tests/bats/bats.bats | 4 ++-- integration-tests/bats/config.bats | 1 - integration-tests/bats/dump.bats | 10 +++++----- integration-tests/bats/export-tables.bats | 2 ++ integration-tests/bats/log.bats | 3 ++- integration-tests/bats/regression-tests.bats | 1 + integration-tests/bats/sql-diff.bats | 2 +- integration-tests/bats/sql-server.bats | 7 +++++-- integration-tests/bats/sql-shell.bats | 5 +++++ integration-tests/bats/sql.bats | 1 + integration-tests/bats/status.bats | 2 +- integration-tests/bats/validation.bats | 2 +- 12 files changed, 26 insertions(+), 14 deletions(-) diff --git a/integration-tests/bats/bats.bats b/integration-tests/bats/bats.bats index c97f79e32d..9e64a0b200 100644 --- a/integration-tests/bats/bats.bats +++ b/integration-tests/bats/bats.bats @@ -3,9 +3,9 @@ # Assert that all bash test constructs will correctly fail on Mac OS's older bash version # by ending them with '|| false'. # https://github.com/sstephenson/bats/issues/49 -@test "bats: all bash test constructs end with '|| false' { +@test "bats: all bash test constructs end with '|| false'" { run grep -E ' *\]\][[:space:]]*$' -n *.bats # grep returns 0 if matches are found, 1 if matches are NOT found, and 2 if no input files were found echo -e "Incorrect bash test constructs: \n$output" [ $status -eq 1 ] -} \ No newline at end of file +} diff --git a/integration-tests/bats/config.bats b/integration-tests/bats/config.bats index f9e0cf0b32..32a6586626 100644 --- a/integration-tests/bats/config.bats +++ b/integration-tests/bats/config.bats @@ -36,7 +36,6 @@ teardown() { [ "$status" -eq 0 ] # Need to make this a regex because of the coloring [[ "$output" =~ "Config successfully updated" ]] || false - [ -f `nativepath ~/.dolt/config_global.json` ] run dolt config --list [ "$status" -eq 0 ] [ "$output" = "test = test" ] diff --git a/integration-tests/bats/dump.bats b/integration-tests/bats/dump.bats index 622c3b7296..43c3ca4de9 100644 --- a/integration-tests/bats/dump.bats +++ b/integration-tests/bats/dump.bats @@ -151,7 +151,7 @@ teardown() { [[ "$output" =~ "3,Table" ]] || false } -@test "dump: SQL type - compare tables in database with tables imported file " { +@test "dump: SQL type - compare tables in database with tables imported file" { dolt branch new_branch dolt sql -q "CREATE TABLE new_table(pk int primary key);" dolt sql -q "INSERT INTO new_table VALUES (1);" @@ -176,7 +176,7 @@ teardown() { [[ "$output" = "" ]] || false } -@test "dump: SQL type (no-batch) - compare tables in database with tables imported file " { +@test "dump: SQL type (no-batch) - compare tables in database with tables imported file" { dolt branch new_branch dolt sql -q "CREATE TABLE new_table(pk int primary key);" @@ -207,7 +207,7 @@ teardown() { [[ "$output" = "" ]] || false } -@test "dump: SQL type (batch is no-op) - compare tables in database with tables imported file " { +@test "dump: SQL type (batch is no-op) - compare tables in database with tables imported file" { dolt branch new_branch dolt sql -q "CREATE TABLE warehouse(warehouse_id int primary key, warehouse_name longtext);" @@ -520,7 +520,7 @@ SQL [ -f doltdump/warehouse.csv ] } -@test "dump: CSV type - compare tables in database with tables imported from corresponding files " { +@test "dump: CSV type - compare tables in database with tables imported from corresponding files" { create_tables dolt add . @@ -660,7 +660,7 @@ SQL [ -f doltdump/warehouse.json ] } -@test "dump: JSON type - compare tables in database with tables imported from corresponding files " { +@test "dump: JSON type - compare tables in database with tables imported from corresponding files" { create_tables dolt add . diff --git a/integration-tests/bats/export-tables.bats b/integration-tests/bats/export-tables.bats index eee1f02d33..a85aee3184 100644 --- a/integration-tests/bats/export-tables.bats +++ b/integration-tests/bats/export-tables.bats @@ -419,7 +419,9 @@ print(df) table = pq.read_table('dt.parquet') print(table.to_pandas()) " > arrow_test.py + run python3 arrow_test.py + [ "$output" = "$panda_result" ] echo "import pandas as pd diff --git a/integration-tests/bats/log.bats b/integration-tests/bats/log.bats index 772110a643..e44de1f1b0 100755 --- a/integration-tests/bats/log.bats +++ b/integration-tests/bats/log.bats @@ -710,6 +710,7 @@ teardown() { [[ "$output" =~ "invalid --decorate option" ]] || false } +# bats test_tags=no_lambda @test "log: check pager" { skiponwindows "Need to install expect and make this script work on windows." dolt commit --allow-empty -m "commit 1" @@ -747,4 +748,4 @@ teardown() { [[ ! "$output" =~ "HEAD" ]] || false run dolt log commit2 [[ "$output" =~ "HEAD" ]] || false -} \ No newline at end of file +} diff --git a/integration-tests/bats/regression-tests.bats b/integration-tests/bats/regression-tests.bats index 5cfbd79394..354cd9e589 100644 --- a/integration-tests/bats/regression-tests.bats +++ b/integration-tests/bats/regression-tests.bats @@ -52,6 +52,7 @@ SQL [[ "${#lines[@]}" = "2" ]] || false } +# bats test_tags=no_lambda @test "regression-tests: UNIQUE index violations do not break future INSERTs" { skiponwindows "Need to install expect and make this script work on windows." mkdir doltsql diff --git a/integration-tests/bats/sql-diff.bats b/integration-tests/bats/sql-diff.bats index 7c9d0ed52a..37aa0b8f65 100644 --- a/integration-tests/bats/sql-diff.bats +++ b/integration-tests/bats/sql-diff.bats @@ -130,7 +130,7 @@ SQL [ "$output" = "" ] } -@test "sql-diff: output reconciles change to PRIMARY KEY field in row " { +@test "sql-diff: output reconciles change to PRIMARY KEY field in row" { dolt checkout -b firstbranch dolt sql < Date: Tue, 5 Dec 2023 16:50:28 -0800 Subject: [PATCH 41/63] integration-tests/bats/performance.bats: Run some long-running tests locally for now. --- integration-tests/bats/performance.bats | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration-tests/bats/performance.bats b/integration-tests/bats/performance.bats index a3b397b432..de15cc3fd3 100644 --- a/integration-tests/bats/performance.bats +++ b/integration-tests/bats/performance.bats @@ -86,7 +86,7 @@ setup() { BATS_TEST_TIMEOUT=1 } - +# bats test_tags=no_lambda @test "performance: merge with schema change and no conflict" { dolt checkout full dolt checkout -b mod2 @@ -118,6 +118,7 @@ setup() { log_status_eq 0 } +# bats test_tags=no_lambda @test "performance: merge with schema change and conflict" { dolt checkout full dolt checkout -b mod2 From ee881448cbd77e3788981534b7d399ba8434ef71 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Tue, 5 Dec 2023 12:32:38 -0800 Subject: [PATCH 42/63] add cli docs and help text for dolt version --- go/cmd/dolt/commands/version.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index fd13c24fe8..9341d6c043 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -29,6 +29,14 @@ const ( verboseFlag = "verbose" ) +var versionDocs = cli.CommandDocumentationContent{ + ShortDesc: "Displays the version for the Dolt binary.", + LongDesc: `Displays the version for the Dolt binary.`, + Synopsis: []string{ + `[--verbose] [--feature]`, + }, +} + type VersionCmd struct { VersionStr string } @@ -40,7 +48,7 @@ func (cmd VersionCmd) Name() string { // Description returns a description of the command func (cmd VersionCmd) Description() string { - return "Displays the current Dolt cli version." + return versionDocs.ShortDesc } // RequiresRepo should return false if this interface is implemented, and the command does not have the requirement @@ -50,7 +58,8 @@ func (cmd VersionCmd) RequiresRepo() bool { } func (cmd VersionCmd) Docs() *cli.CommandDocumentation { - return nil + ap := cmd.ArgParser() + return cli.NewCommandDocumentation(versionDocs, ap) } func (cmd VersionCmd) ArgParser() *argparser.ArgParser { @@ -63,11 +72,11 @@ func (cmd VersionCmd) ArgParser() *argparser.ArgParser { // Version displays the version of the running dolt client // Exec executes the command func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { - cli.Println("dolt version", cmd.VersionStr) - - usage := func() {} ap := cmd.ArgParser() - apr := cli.ParseArgsOrDie(ap, args, usage) + help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, versionDocs, ap)) + apr := cli.ParseArgsOrDie(ap, args, help) + + cli.Println("dolt version", cmd.VersionStr) if apr.Contains(verboseFlag) { if dEnv.HasDoltDir() && dEnv.RSLoadErr == nil && !cli.CheckEnvIsValid(dEnv) { From eae7329c57403a909fa20aa52a89f19d01040a16 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Tue, 5 Dec 2023 12:37:21 -0800 Subject: [PATCH 43/63] version checks latest release --- go/cmd/dolt/commands/version.go | 16 +++++++++++++++- go/go.mod | 3 ++- go/go.sum | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index 9341d6c043..437ac8bfe0 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -16,12 +16,14 @@ package commands import ( "context" + "strings" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/google/go-github/v57/github" ) const ( @@ -78,6 +80,19 @@ func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string cli.Println("dolt version", cmd.VersionStr) + var verr errhand.VerboseError + // out of date check + client := github.NewClient(nil) + release, resp, err := client.Repositories.GetLatestRelease(ctx, "dolthub", "dolt") + if err != nil || resp.StatusCode != 200 { + verr = errhand.BuildDError("error: failed to get latest release").AddCause(err).Build() + return HandleVErrAndExitCode(verr, usage) + } + releaseName := strings.TrimPrefix(*release.TagName, "v") + if cmd.VersionStr != releaseName { + cli.Printf("Warning: you are on an old version of Dolt. The newest version is %s.\n", releaseName) + } + if apr.Contains(verboseFlag) { if dEnv.HasDoltDir() && dEnv.RSLoadErr == nil && !cli.CheckEnvIsValid(dEnv) { return 2 @@ -87,7 +102,6 @@ func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string } } - var verr errhand.VerboseError if apr.Contains(featureVersionFlag) { if !cli.CheckEnvIsValid(dEnv) { return 2 diff --git a/go/go.mod b/go/go.mod index a32d8c0e9a..8151bf8c75 100644 --- a/go/go.mod +++ b/go/go.mod @@ -114,7 +114,8 @@ require ( github.com/go-pdf/fpdf v0.6.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-github/v57 v57.0.0 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.11.0 // indirect diff --git a/go/go.sum b/go/go.sum index 54e07639ec..4dba9572b4 100644 --- a/go/go.sum +++ b/go/go.sum @@ -328,6 +328,10 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs= +github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= From 3fc766e4dbe4ac91c15a35035bf49452718c7305 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Tue, 5 Dec 2023 17:24:43 -0800 Subject: [PATCH 44/63] restrict checking latest release to once per week --- go/cmd/dolt/commands/version.go | 81 +++++++++++++++++++++++++++++---- go/go.mod | 3 +- go/go.sum | 5 +- 3 files changed, 77 insertions(+), 12 deletions(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index 437ac8bfe0..196f7a0935 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -16,10 +16,15 @@ package commands import ( "context" + "fmt" + "os" + "path/filepath" "strings" + "time" "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" + "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions" "github.com/dolthub/dolt/go/libraries/utils/argparser" @@ -29,6 +34,7 @@ import ( const ( featureVersionFlag = "feature" verboseFlag = "verbose" + versionCheckFile = "version_check.txt" ) var versionDocs = cli.CommandDocumentationContent{ @@ -81,17 +87,10 @@ func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string cli.Println("dolt version", cmd.VersionStr) var verr errhand.VerboseError - // out of date check - client := github.NewClient(nil) - release, resp, err := client.Repositories.GetLatestRelease(ctx, "dolthub", "dolt") - if err != nil || resp.StatusCode != 200 { - verr = errhand.BuildDError("error: failed to get latest release").AddCause(err).Build() + verr = checkAndPrintVersionOutOfDateWarning(cmd.VersionStr, dEnv) + if verr != nil { return HandleVErrAndExitCode(verr, usage) } - releaseName := strings.TrimPrefix(*release.TagName, "v") - if cmd.VersionStr != releaseName { - cli.Printf("Warning: you are on an old version of Dolt. The newest version is %s.\n", releaseName) - } if apr.Contains(verboseFlag) { if dEnv.HasDoltDir() && dEnv.RSLoadErr == nil && !cli.CheckEnvIsValid(dEnv) { @@ -124,3 +123,67 @@ func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string return HandleVErrAndExitCode(verr, usage) } + +// checkAndPrintVersionOutOfDateWarning checks if the current version of Dolt is out of date and prints a warning if it +// is. Restricts this check to at most once per week. +func checkAndPrintVersionOutOfDateWarning(curVersion string, dEnv *env.DoltEnv) errhand.VerboseError { + var latestRelease string + var verr errhand.VerboseError + + homeDir, err := dEnv.GetUserHomeDir() + if err != nil { + return errhand.BuildDError("error: failed to get user home directory").AddCause(err).Build() + } + path := filepath.Join(homeDir, dbfactory.DoltDir, versionCheckFile) + + if exists, _ := dEnv.FS.Exists(path); exists { + vCheck, err := dEnv.FS.ReadFile(path) + if err != nil { + return errhand.BuildDError("error: failed to read version check file").AddCause(err).Build() + } + + vCheckData := strings.Split(string(vCheck), ",") + if len(vCheckData) != 2 { + // formatting or data is wrong, so just overwrite + latestRelease, verr = getLatestDoltReleaseAndRecord(path, dEnv) + if verr != nil { + return verr + } + } else { + latestRelease = vCheckData[0] + lastCheckDate, err := time.Parse(time.DateOnly, vCheckData[1]) + if err != nil { + return errhand.BuildDError("error: failed to parse version check file").AddCause(err).Build() + } + if lastCheckDate.Before(time.Now().AddDate(0, 0, -7)) { + latestRelease, err = getLatestDoltReleaseAndRecord(path, dEnv) + } + } + } else { + latestRelease, err = getLatestDoltReleaseAndRecord(path, dEnv) + } + + if curVersion != latestRelease { + cli.Printf("Warning: you are on an old version of Dolt. The newest version is %s.\n", latestRelease) + } + + return nil +} + +// getLatestDoltRelease returns the latest release of Dolt from GitHub and records the release and current date in the +// version check file. +func getLatestDoltReleaseAndRecord(path string, dEnv *env.DoltEnv) (string, errhand.VerboseError) { + client := github.NewClient(nil) + release, resp, err := client.Repositories.GetLatestRelease(context.Background(), "dolthub", "dolt") + if err != nil || resp.StatusCode != 200 { + return "", errhand.BuildDError("error: failed to get latest release").AddCause(err).Build() + } + releaseName := strings.TrimPrefix(*release.TagName, "v") + + err = dEnv.FS.WriteFile(path, []byte(fmt.Sprintf("%s,%s", releaseName, time.Now().UTC().Format(time.DateOnly))), os.ModePerm) + if err != nil { + return "", errhand.BuildDError("error: failed to update version check file").AddCause(err).Build() + } + + return releaseName, nil +} diff --git a/go/go.mod b/go/go.mod index 8151bf8c75..01b278d1e3 100644 --- a/go/go.mod +++ b/go/go.mod @@ -62,6 +62,7 @@ require ( github.com/dolthub/go-mysql-server v0.17.1-0.20231205222834-2eb85072ed9d github.com/dolthub/swiss v0.1.0 github.com/goccy/go-json v0.10.2 + github.com/google/go-github/v57 v57.0.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/hashicorp/golang-lru/v2 v2.0.2 github.com/jmoiron/sqlx v1.3.4 @@ -115,7 +116,7 @@ require ( github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-github/v57 v57.0.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.11.0 // indirect diff --git a/go/go.sum b/go/go.sum index 4dba9572b4..1e3cba64b5 100644 --- a/go/go.sum +++ b/go/go.sum @@ -321,17 +321,18 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs= github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= From d22b62393b59292f98908a01aac20eb04d40ada9 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Tue, 5 Dec 2023 17:52:28 -0800 Subject: [PATCH 45/63] license update --- go/Godeps/LICENSES | 555 ++++++++++++++++++++++++++++----------------- 1 file changed, 345 insertions(+), 210 deletions(-) diff --git a/go/Godeps/LICENSES b/go/Godeps/LICENSES index 75644cb458..a06b1fde17 100644 --- a/go/Godeps/LICENSES +++ b/go/Godeps/LICENSES @@ -241,215 +241,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. = LICENSE ed6066ae50f153e2965216c6d4b9335900f1f8b2b526527f49a619d7 = ================================================================================ -================================================================================ -= ./gen/proto/dolt/services/eventsapi licensed under: = - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -= LICENSE 75cd5500580317e758b5e984e017524dc961140e4889f7d427f85e41 = -================================================================================ - ================================================================================ = cloud.google.com/go licensed under: = @@ -5034,6 +4825,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. = LICENSE bda64ae869be18b50125d9cfe5c370eb7248e84a2324823e4d7f2295 = ================================================================================ +================================================================================ += github.com/google/go-github/v57 licensed under: = + +Copyright (c) 2013 The go-github AUTHORS. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += LICENSE 4f95ee9c8c81d66113b4c4fe66b684ae243884b5947ee854319dd9cc = +================================================================================ + +================================================================================ += github.com/google/go-querystring licensed under: = + +Copyright (c) 2013 Google. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + += LICENSE 7b97c9585df42dc638169348f6350b491fc35fe50884a7e6cf41aa58 = +================================================================================ + ================================================================================ = github.com/google/s2a-go licensed under: = @@ -6593,7 +6452,283 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -= LICENSE b6f05c0b9dba1bb0e91a34890d46579fbbc42d0b80de9ce3194d06f3 = +------------------ + +Files: gzhttp/* + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016-2017 The New York Times Company + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +------------------ + +Files: s2/cmd/internal/readahead/* + +The MIT License (MIT) + +Copyright (c) 2015 Klaus Post + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------- +Files: snappy/* +Files: internal/snapref/* + +Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +----------------- + +Files: s2/cmd/internal/filepathx/* + +Copyright 2016 The filepathx Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + += LICENSE ab09e77acafc29821ababe88d617e81bf26ea8aa6f21f3ca9b86de18 = ================================================================================ ================================================================================ From 0e1bbfc9f0c074c2ece97d9aa31df2f502cd3287 Mon Sep 17 00:00:00 2001 From: Aaron Son Date: Wed, 6 Dec 2023 09:03:32 -0800 Subject: [PATCH 46/63] go/libraries/doltcore/sqle: DatabaseProvider: Fix a bug where a database created with call dolt_clone() would not be dropped until the server was restarted. Fixes #7106. --- .../doltcore/sqle/database_provider.go | 42 ++++--------------- integration-tests/bats/clone-drop.bats | 31 ++++++++++++++ .../bats/helper/local-remote.bash | 1 + 3 files changed, 40 insertions(+), 34 deletions(-) create mode 100644 integration-tests/bats/clone-drop.bats diff --git a/go/libraries/doltcore/sqle/database_provider.go b/go/libraries/doltcore/sqle/database_provider.go index 4113578600..3a83c4ba4b 100644 --- a/go/libraries/doltcore/sqle/database_provider.go +++ b/go/libraries/doltcore/sqle/database_provider.go @@ -485,7 +485,7 @@ func (p *DoltDatabaseProvider) CloneDatabaseFromRemote( return fmt.Errorf("cannot create DB, file exists at %s", dbName) } - dEnv, err := p.cloneDatabaseFromRemote(ctx, dbName, remoteName, branch, remoteUrl, remoteParams) + err := p.cloneDatabaseFromRemote(ctx, dbName, remoteName, branch, remoteUrl, remoteParams) if err != nil { // Make a best effort to clean up any artifacts on disk from a failed clone // before we return the error @@ -499,7 +499,7 @@ func (p *DoltDatabaseProvider) CloneDatabaseFromRemote( return err } - return ConfigureReplicationDatabaseHook(ctx, p, dbName, dEnv) + return nil } // cloneDatabaseFromRemote encapsulates the inner logic for cloning a database so that if any error @@ -510,26 +510,26 @@ func (p *DoltDatabaseProvider) cloneDatabaseFromRemote( ctx *sql.Context, dbName, remoteName, branch, remoteUrl string, remoteParams map[string]string, -) (*env.DoltEnv, error) { +) error { if p.remoteDialer == nil { - return nil, fmt.Errorf("unable to clone remote database; no remote dialer configured") + return fmt.Errorf("unable to clone remote database; no remote dialer configured") } // TODO: params for AWS, others that need them r := env.NewRemote(remoteName, remoteUrl, nil) srcDB, err := r.GetRemoteDB(ctx, types.Format_Default, p.remoteDialer) if err != nil { - return nil, err + return err } dEnv, err := actions.EnvForClone(ctx, srcDB.ValueReadWriter().Format(), r, dbName, p.fs, "VERSION", env.GetCurrentUserHomeDir) if err != nil { - return nil, err + return err } err = actions.CloneRemote(ctx, srcDB, remoteName, branch, dEnv) if err != nil { - return nil, err + return err } err = dEnv.RepoStateWriter().UpdateBranch(dEnv.RepoState.CWBHeadRef().GetPath(), env.BranchConfig{ @@ -537,33 +537,7 @@ func (p *DoltDatabaseProvider) cloneDatabaseFromRemote( Remote: remoteName, }) - fkChecks, err := ctx.GetSessionVariable(ctx, "foreign_key_checks") - if err != nil { - return nil, err - } - - opts := editor.Options{ - Deaf: dEnv.DbEaFactory(), - // TODO: this doesn't seem right, why is this getting set in the constructor to the DB - ForeignKeyChecksDisabled: fkChecks.(int8) == 0, - } - - db, err := NewDatabase(ctx, dbName, dEnv.DbData(), opts) - if err != nil { - return nil, err - } - - // If we have an initialization hook, invoke it. By default, this will - // be ConfigureReplicationDatabaseHook, which will setup replication - // for the new database if a remote url template is set. - err = p.InitDatabaseHook(ctx, p, dbName, dEnv) - if err != nil { - return nil, err - } - - p.databases[formatDbMapKeyName(db.Name())] = db - - return dEnv, nil + return p.registerNewDatabase(ctx, dbName, dEnv) } // DropDatabase implements the sql.MutableDatabaseProvider interface diff --git a/integration-tests/bats/clone-drop.bats b/integration-tests/bats/clone-drop.bats new file mode 100644 index 0000000000..7e4785b7a3 --- /dev/null +++ b/integration-tests/bats/clone-drop.bats @@ -0,0 +1,31 @@ +#!/usr/bin/env bats +load $BATS_TEST_DIRNAME/helper/common.bash + +setup() { + setup_no_dolt_init +} + +teardown() { + stop_sql_server + assert_feature_version + teardown_common +} + +@test "clone-drop: clone a database and then drop it" { + mkdir repo + cd repo + dolt init + dolt remote add pushed 'file://../pushed' + dolt push pushed main:main + dolt sql -q 'call dolt_clone("file://../pushed", "cloned"); drop database cloned;' +} + +@test "clone-drop: sql-server: clone a database and then drop it" { + mkdir repo + cd repo + dolt init + dolt remote add pushed 'file://../pushed' + dolt push pushed main:main + start_sql_server + dolt sql -q 'call dolt_clone("file://../pushed", "cloned"); drop database cloned;' +} diff --git a/integration-tests/bats/helper/local-remote.bash b/integration-tests/bats/helper/local-remote.bash index f478ffa6b9..7b8c428ff8 100644 --- a/integration-tests/bats/helper/local-remote.bash +++ b/integration-tests/bats/helper/local-remote.bash @@ -22,6 +22,7 @@ SKIP_SERVER_TESTS=$(cat <<-EOM ~1pk5col-strings.bats~ ~sql-tags.bats~ ~empty-repo.bats~ +~clone-drops.bats~ ~verify-constraints.bats~ ~db-revision-specifiers.bats~ ~ignore.bats~ From 23c229fa59b5ba48fe4af7fb588463d07eb44037 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Wed, 6 Dec 2023 09:48:04 -0800 Subject: [PATCH 47/63] PR feedback --- go/libraries/events/emitter.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index 2eacaaca77..d8df06e976 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -32,6 +32,8 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/iohelp" ) +// Application is the application ID used for all events emitted by this application. Other applications (not dolt) +// should set this once at initialization. var Application = eventsapi.AppID_APP_DOLT // EmitterTypeEnvVar is the environment variable DOLT_EVENTS_EMITTER, which you can set to one of the values below From b756f73a81ddc8a3dd475499a5e8da6f6b2034e2 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Wed, 6 Dec 2023 10:21:39 -0800 Subject: [PATCH 48/63] fix bats test --- integration-tests/bats/no-repo.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/bats/no-repo.bats b/integration-tests/bats/no-repo.bats index d87a8e13ef..c36d28c1fb 100755 --- a/integration-tests/bats/no-repo.bats +++ b/integration-tests/bats/no-repo.bats @@ -59,7 +59,7 @@ teardown() { [[ "$output" =~ "gc - Cleans up unreferenced data from the repository." ]] || false [[ "$output" =~ "filter-branch - Edits the commit history using the provided query." ]] || false [[ "$output" =~ "merge-base - Find the common ancestor of two commits." ]] || false - [[ "$output" =~ "version - Displays the current Dolt cli version." ]] || false + [[ "$output" =~ "version - Displays the version for the Dolt binary." ]] || false [[ "$output" =~ "dump - Export all tables in the working set into a file." ]] || false } From b4167b987e4a8b2f541dda3a573aefd728b31261 Mon Sep 17 00:00:00 2001 From: Jason Fulghum Date: Wed, 6 Dec 2023 11:59:25 -0800 Subject: [PATCH 49/63] Refactoring cherry pick logic out of the dprocedure package and into a new cherry_pick package --- .../doltcore/cherry_pick/cherry_pick.go | 293 ++++++++++++++++++ go/libraries/doltcore/merge/action.go | 47 +++ .../sqle/dprocedures/dolt_cherry_pick.go | 209 +------------ .../doltcore/sqle/dprocedures/dolt_merge.go | 39 +-- 4 files changed, 351 insertions(+), 237 deletions(-) create mode 100644 go/libraries/doltcore/cherry_pick/cherry_pick.go diff --git a/go/libraries/doltcore/cherry_pick/cherry_pick.go b/go/libraries/doltcore/cherry_pick/cherry_pick.go new file mode 100644 index 0000000000..f288bdcac2 --- /dev/null +++ b/go/libraries/doltcore/cherry_pick/cherry_pick.go @@ -0,0 +1,293 @@ +// Copyright 2023 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cherry_pick + +import ( + "errors" + "fmt" + + "github.com/dolthub/go-mysql-server/sql" + + "github.com/dolthub/dolt/go/libraries/doltcore/diff" + "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" + "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" + "github.com/dolthub/dolt/go/libraries/doltcore/merge" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" +) + +// ErrCherryPickUncommittedChanges is returned when a cherry-pick is attempted without a clean working set. +var ErrCherryPickUncommittedChanges = errors.New("cannot cherry-pick with uncommitted changes") + +// CherryPickOptions specifies optional parameters specifying how a cherry-pick is performed. +type CherryPickOptions struct { + // Amend controls whether the commit at HEAD is amended and combined with the commit to be cherry-picked. + Amend bool + + // CommitMessage is optional, and controls the message for the new commit. + CommitMessage string +} + +// CherryPick replays a commit, specified by |options.Commit|, and applies it as a new commit to the current HEAD. If +// successful, the hash of the new commit is returned. If the cherry-pick results in merge conflicts, the merge result +// is returned. If any unexpected error occur, it is returned. +func CherryPick(ctx *sql.Context, commit string, options CherryPickOptions) (string, *merge.Result, error) { + doltSession := dsess.DSessFromSess(ctx.Session) + dbName := ctx.GetCurrentDatabase() + + roots, ok := doltSession.GetRoots(ctx, dbName) + if !ok { + return "", nil, fmt.Errorf("failed to get roots for current session") + } + + mergeResult, commitMsg, err := cherryPick(ctx, doltSession, roots, dbName, commit) + if err != nil { + return "", nil, err + } + + newWorkingRoot := mergeResult.Root + err = doltSession.SetRoot(ctx, dbName, newWorkingRoot) + if err != nil { + return "", nil, err + } + + err = stageCherryPickedTables(ctx, mergeResult.Stats) + if err != nil { + return "", nil, err + } + + // If there were merge conflicts, just return the merge result. + if mergeResult.HasMergeArtifacts() { + return "", mergeResult, nil + } + + commitProps := actions.CommitStagedProps{ + Date: ctx.QueryTime(), + Name: ctx.Client().User, + Email: fmt.Sprintf("%s@%s", ctx.Client().User, ctx.Client().Address), + Message: commitMsg, + } + + if options.CommitMessage != "" { + commitProps.Message = options.CommitMessage + } + if options.Amend { + commitProps.Amend = true + } + + // NOTE: roots are old here (after staging the tables) and need to be refreshed + roots, ok = doltSession.GetRoots(ctx, dbName) + if !ok { + return "", nil, fmt.Errorf("failed to get roots for current session") + } + + pendingCommit, err := doltSession.NewPendingCommit(ctx, dbName, roots, commitProps) + if err != nil { + return "", nil, err + } + if pendingCommit == nil { + return "", nil, errors.New("nothing to commit") + } + + newCommit, err := doltSession.DoltCommit(ctx, dbName, doltSession.GetTransaction(), pendingCommit) + if err != nil { + return "", nil, err + } + + h, err := newCommit.HashOf() + if err != nil { + return "", nil, err + } + + return h.String(), nil, nil +} + +// AbortCherryPick aborts a cherry-pick merge, if one is in progress. If unable to abort for any reason +// (e.g. if there is not cherry-pick merge in progress), an error is returned. +func AbortCherryPick(ctx *sql.Context, dbName string) error { + doltSession := dsess.DSessFromSess(ctx.Session) + + ws, err := doltSession.WorkingSet(ctx, dbName) + if err != nil { + return fmt.Errorf("fatal: unable to load working set: %v", err) + } + + if !ws.MergeActive() { + return fmt.Errorf("error: There is no cherry-pick merge to abort") + } + + roots, ok := doltSession.GetRoots(ctx, dbName) + if !ok { + return fmt.Errorf("fatal: unable to load roots for %s", dbName) + } + + newWs, err := merge.AbortMerge(ctx, ws, roots) + if err != nil { + return fmt.Errorf("fatal: unable to abort merge: %v", err) + } + + return doltSession.SetWorkingSet(ctx, dbName, newWs) +} + +// cherryPick checks that the current working set is clean, verifies the cherry-pick commit is not a merge commit +// or a commit without parent commit, performs merge and returns the new working set root value and +// the commit message of cherry-picked commit as the commit message of the new commit created during this command. +func cherryPick(ctx *sql.Context, dSess *dsess.DoltSession, roots doltdb.Roots, dbName, cherryStr string) (*merge.Result, string, error) { + // check for clean working set + wsOnlyHasIgnoredTables, err := diff.WorkingSetContainsOnlyIgnoredTables(ctx, roots) + if err != nil { + return nil, "", err + } + if !wsOnlyHasIgnoredTables { + return nil, "", ErrCherryPickUncommittedChanges + } + + headRootHash, err := roots.Head.HashOf() + if err != nil { + return nil, "", err + } + + workingRootHash, err := roots.Working.HashOf() + if err != nil { + return nil, "", err + } + + doltDB, ok := dSess.GetDoltDB(ctx, dbName) + if !ok { + return nil, "", fmt.Errorf("failed to get DoltDB") + } + + dbData, ok := dSess.GetDbData(ctx, dbName) + if !ok { + return nil, "", fmt.Errorf("failed to get dbData") + } + + cherryCommitSpec, err := doltdb.NewCommitSpec(cherryStr) + if err != nil { + return nil, "", err + } + headRef, err := dbData.Rsr.CWBHeadRef() + if err != nil { + return nil, "", err + } + cherryCommit, err := doltDB.Resolve(ctx, cherryCommitSpec, headRef) + if err != nil { + return nil, "", err + } + + if len(cherryCommit.DatasParents()) > 1 { + return nil, "", fmt.Errorf("cherry-picking a merge commit is not supported") + } + if len(cherryCommit.DatasParents()) == 0 { + return nil, "", fmt.Errorf("cherry-picking a commit without parents is not supported") + } + + cherryRoot, err := cherryCommit.GetRootValue(ctx) + if err != nil { + return nil, "", err + } + + // When cherry-picking, we need to use the parent of the cherry-picked commit as the ancestor. This + // ensures that only the delta from the cherry-pick commit is applied. + parentCommit, err := doltDB.ResolveParent(ctx, cherryCommit, 0) + if err != nil { + return nil, "", err + } + parentRoot, err := parentCommit.GetRootValue(ctx) + if err != nil { + return nil, "", err + } + + dbState, ok, err := dSess.LookupDbState(ctx, dbName) + if err != nil { + return nil, "", err + } else if !ok { + return nil, "", sql.ErrDatabaseNotFound.New(dbName) + } + + mo := merge.MergeOpts{ + IsCherryPick: true, + KeepSchemaConflicts: false, + } + result, err := merge.MergeRoots(ctx, roots.Working, cherryRoot, parentRoot, cherryCommit, parentCommit, dbState.EditOpts(), mo) + if err != nil { + return nil, "", err + } + + workingRootHash, err = result.Root.HashOf() + if err != nil { + return nil, "", err + } + + if headRootHash.Equal(workingRootHash) { + return nil, "", fmt.Errorf("no changes were made, nothing to commit") + } + + cherryCommitMeta, err := cherryCommit.GetCommitMeta(ctx) + if err != nil { + return nil, "", err + } + + // If any of the merge stats show a data or schema conflict or a constraint + // violation, record that a merge is in progress. + for _, stats := range result.Stats { + if stats.HasArtifacts() { + ws, err := dSess.WorkingSet(ctx, dbName) + if err != nil { + return nil, "", err + } + newWorkingSet := ws.StartCherryPick(cherryCommit, cherryStr) + err = dSess.SetWorkingSet(ctx, dbName, newWorkingSet) + if err != nil { + return nil, "", err + } + + break + } + } + + return result, cherryCommitMeta.Description, nil +} + +// stageCherryPickedTables stages the tables from |mergeStats| that don't have any merge artifacts – i.e. +// tables that don't have any data or schema conflicts and don't have any constraint violations. +func stageCherryPickedTables(ctx *sql.Context, mergeStats map[string]*merge.MergeStats) (err error) { + tablesToAdd := make([]string, 0, len(mergeStats)) + for tableName, mergeStats := range mergeStats { + if mergeStats.HasArtifacts() { + continue + } + + // Find any tables being deleted and make sure we stage those tables first + if mergeStats.Operation == merge.TableRemoved { + tablesToAdd = append([]string{tableName}, tablesToAdd...) + } else { + tablesToAdd = append(tablesToAdd, tableName) + } + } + + doltSession := dsess.DSessFromSess(ctx.Session) + dbName := ctx.GetCurrentDatabase() + roots, ok := doltSession.GetRoots(ctx, dbName) + if !ok { + return fmt.Errorf("unable to get roots for database '%s' from session", dbName) + } + + roots, err = actions.StageTables(ctx, roots, tablesToAdd, true) + if err != nil { + return err + } + + return doltSession.SetRoots(ctx, dbName, roots) +} diff --git a/go/libraries/doltcore/merge/action.go b/go/libraries/doltcore/merge/action.go index e824d0a7ab..d16643a6f2 100644 --- a/go/libraries/doltcore/merge/action.go +++ b/go/libraries/doltcore/merge/action.go @@ -24,6 +24,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/env" + "github.com/dolthub/dolt/go/libraries/doltcore/env/actions" "github.com/dolthub/dolt/go/libraries/doltcore/table/editor" "github.com/dolthub/dolt/go/store/hash" ) @@ -281,3 +282,49 @@ func mergedRootToWorking( } return } + +// AbortMerge returns a new WorkingSet instance, with the active merge aborted, by clearing and +// resetting the merge state in |workingSet| and using |roots| to identify the existing tables +// and reset them, excluding any ignored tables. The caller must then set the new WorkingSet in +// the session before the aborted merge is finalized. If no merge is in progress, this function +// returns an error. +func AbortMerge(ctx *sql.Context, workingSet *doltdb.WorkingSet, roots doltdb.Roots) (*doltdb.WorkingSet, error) { + if !workingSet.MergeActive() { + return nil, fmt.Errorf("there is no merge to abort") + } + + tbls, err := doltdb.UnionTableNames(ctx, roots.Working, roots.Staged, roots.Head) + if err != nil { + return nil, err + } + + roots, err = actions.MoveTablesFromHeadToWorking(ctx, roots, tbls) + if err != nil { + return nil, err + } + + preMergeWorkingRoot := workingSet.MergeState().PreMergeWorkingRoot() + preMergeWorkingTables, err := preMergeWorkingRoot.GetTableNames(ctx) + if err != nil { + return nil, err + } + nonIgnoredTables, err := doltdb.ExcludeIgnoredTables(ctx, roots, preMergeWorkingTables) + if err != nil { + return nil, err + } + someTablesAreIgnored := len(nonIgnoredTables) != len(preMergeWorkingTables) + + if someTablesAreIgnored { + newWorking, err := actions.MoveTablesBetweenRoots(ctx, nonIgnoredTables, preMergeWorkingRoot, roots.Working) + if err != nil { + return nil, err + } + workingSet = workingSet.WithWorkingRoot(newWorking) + } else { + workingSet = workingSet.WithWorkingRoot(preMergeWorkingRoot) + } + workingSet = workingSet.WithStagedRoot(workingSet.WorkingRoot()) + workingSet = workingSet.ClearMerge() + + return workingSet, nil +} diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_cherry_pick.go b/go/libraries/doltcore/sqle/dprocedures/dolt_cherry_pick.go index f59812d374..645f9bafe3 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_cherry_pick.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_cherry_pick.go @@ -23,14 +23,10 @@ import ( "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/libraries/doltcore/branch_control" - "github.com/dolthub/dolt/go/libraries/doltcore/diff" - "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" - "github.com/dolthub/dolt/go/libraries/doltcore/merge" - "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" + "github.com/dolthub/dolt/go/libraries/doltcore/cherry_pick" ) var ErrEmptyCherryPick = errors.New("cannot cherry-pick empty string") -var ErrCherryPickUncommittedChanges = errors.New("cannot cherry-pick with uncommitted changes") var cherryPickSchema = []*sql.Column{ { @@ -83,29 +79,8 @@ func doDoltCherryPick(ctx *sql.Context, args []string) (string, int, int, int, e return "", 0, 0, 0, err } - dSess := dsess.DSessFromSess(ctx.Session) - if apr.Contains(cli.AbortParam) { - ws, err := dSess.WorkingSet(ctx, dbName) - if err != nil { - return "", 0, 0, 0, fmt.Errorf("fatal: unable to load working set: %v", err) - } - - if !ws.MergeActive() { - return "", 0, 0, 0, fmt.Errorf("error: There is no cherry-pick merge to abort") - } - - roots, ok := dSess.GetRoots(ctx, dbName) - if !ok { - return "", 0, 0, 0, fmt.Errorf("fatal: unable to load roots for %s", dbName) - } - - newWs, err := abortMerge(ctx, ws, roots) - if err != nil { - return "", 0, 0, 0, fmt.Errorf("fatal: unable to abort merge: %v", err) - } - - return "", 0, 0, 0, dSess.SetWorkingSet(ctx, dbName, newWs) + return "", 0, 0, 0, cherry_pick.AbortCherryPick(ctx, dbName) } // we only support cherry-picking a single commit for now. @@ -120,182 +95,18 @@ func doDoltCherryPick(ctx *sql.Context, args []string) (string, int, int, int, e return "", 0, 0, 0, ErrEmptyCherryPick } - roots, ok := dSess.GetRoots(ctx, dbName) - if !ok { - return "", 0, 0, 0, sql.ErrDatabaseNotFound.New(dbName) - } - - mergeResult, commitMsg, err := cherryPick(ctx, dSess, roots, dbName, cherryStr) + commit, mergeResult, err := cherry_pick.CherryPick(ctx, cherryStr, cherry_pick.CherryPickOptions{}) if err != nil { return "", 0, 0, 0, err } - newWorkingRoot := mergeResult.Root - err = dSess.SetRoot(ctx, dbName, newWorkingRoot) - if err != nil { - return "", 0, 0, 0, err + if mergeResult != nil { + return "", + mergeResult.CountOfTablesWithDataConflicts(), + mergeResult.CountOfTablesWithSchemaConflicts(), + mergeResult.CountOfTablesWithConstraintViolations(), + nil } - err = stageCherryPickedTables(ctx, mergeResult.Stats) - if err != nil { - return "", 0, 0, 0, err - } - - if mergeResult.HasMergeArtifacts() { - return "", mergeResult.CountOfTablesWithDataConflicts(), - mergeResult.CountOfTablesWithSchemaConflicts(), mergeResult.CountOfTablesWithConstraintViolations(), nil - } else { - commitHash, _, err := doDoltCommit(ctx, []string{"-m", commitMsg}) - return commitHash, 0, 0, 0, err - } -} - -// stageCherryPickedTables stages the tables from |mergeStats| that don't have any merge artifacts – i.e. -// tables that don't have any data or schema conflicts and don't have any constraint violations. -func stageCherryPickedTables(ctx *sql.Context, mergeStats map[string]*merge.MergeStats) error { - tablesToAdd := make([]string, 0, len(mergeStats)) - for tableName, mergeStats := range mergeStats { - if mergeStats.HasArtifacts() { - continue - } - - // Find any tables being deleted and make sure we stage those tables first - if mergeStats.Operation == merge.TableRemoved { - tablesToAdd = append([]string{tableName}, tablesToAdd...) - } else { - tablesToAdd = append(tablesToAdd, tableName) - } - } - - for _, tableName := range tablesToAdd { - res, err := doDoltAdd(ctx, []string{tableName}) - if err != nil { - return err - } - if res != 0 { - return fmt.Errorf("dolt add failed") - } - } - - return nil -} - -// cherryPick checks that the current working set is clean, verifies the cherry-pick commit is not a merge commit -// or a commit without parent commit, performs merge and returns the new working set root value and -// the commit message of cherry-picked commit as the commit message of the new commit created during this command. -func cherryPick(ctx *sql.Context, dSess *dsess.DoltSession, roots doltdb.Roots, dbName, cherryStr string) (*merge.Result, string, error) { - // check for clean working set - wsOnlyHasIgnoredTables, err := diff.WorkingSetContainsOnlyIgnoredTables(ctx, roots) - if err != nil { - return nil, "", err - } - if !wsOnlyHasIgnoredTables { - return nil, "", ErrCherryPickUncommittedChanges - } - - headRootHash, err := roots.Head.HashOf() - if err != nil { - return nil, "", err - } - - workingRootHash, err := roots.Working.HashOf() - if err != nil { - return nil, "", err - } - - doltDB, ok := dSess.GetDoltDB(ctx, dbName) - if !ok { - return nil, "", fmt.Errorf("failed to get DoltDB") - } - - dbData, ok := dSess.GetDbData(ctx, dbName) - if !ok { - return nil, "", fmt.Errorf("failed to get dbData") - } - - cherryCommitSpec, err := doltdb.NewCommitSpec(cherryStr) - if err != nil { - return nil, "", err - } - headRef, err := dbData.Rsr.CWBHeadRef() - if err != nil { - return nil, "", err - } - cherryCommit, err := doltDB.Resolve(ctx, cherryCommitSpec, headRef) - if err != nil { - return nil, "", err - } - - if len(cherryCommit.DatasParents()) > 1 { - return nil, "", fmt.Errorf("cherry-picking a merge commit is not supported") - } - if len(cherryCommit.DatasParents()) == 0 { - return nil, "", fmt.Errorf("cherry-picking a commit without parents is not supported") - } - - cherryRoot, err := cherryCommit.GetRootValue(ctx) - if err != nil { - return nil, "", err - } - - // When cherry-picking, we need to use the parent of the cherry-picked commit as the ancestor. This - // ensures that only the delta from the cherry-pick commit is applied. - parentCommit, err := doltDB.ResolveParent(ctx, cherryCommit, 0) - if err != nil { - return nil, "", err - } - parentRoot, err := parentCommit.GetRootValue(ctx) - if err != nil { - return nil, "", err - } - - dbState, ok, err := dSess.LookupDbState(ctx, dbName) - if err != nil { - return nil, "", err - } else if !ok { - return nil, "", sql.ErrDatabaseNotFound.New(dbName) - } - - mo := merge.MergeOpts{ - IsCherryPick: true, - KeepSchemaConflicts: false, - } - result, err := merge.MergeRoots(ctx, roots.Working, cherryRoot, parentRoot, cherryCommit, parentCommit, dbState.EditOpts(), mo) - if err != nil { - return nil, "", err - } - - workingRootHash, err = result.Root.HashOf() - if err != nil { - return nil, "", err - } - - if headRootHash.Equal(workingRootHash) { - return nil, "", fmt.Errorf("no changes were made, nothing to commit") - } - - cherryCommitMeta, err := cherryCommit.GetCommitMeta(ctx) - if err != nil { - return nil, "", err - } - - // If any of the merge stats show a data or schema conflict or a constraint - // violation, record that a merge is in progress. - for _, stats := range result.Stats { - if stats.HasArtifacts() { - ws, err := dSess.WorkingSet(ctx, dbName) - if err != nil { - return nil, "", err - } - newWorkingSet := ws.StartCherryPick(cherryCommit, cherryStr) - err = dSess.SetWorkingSet(ctx, dbName, newWorkingSet) - if err != nil { - return nil, "", err - } - - break - } - } - - return result, cherryCommitMeta.Description, nil + return commit, 0, 0, 0, nil } diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_merge.go b/go/libraries/doltcore/sqle/dprocedures/dolt_merge.go index e90973a5e4..36189497b7 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_merge.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_merge.go @@ -117,7 +117,7 @@ func doDoltMerge(ctx *sql.Context, args []string) (string, int, int, error) { return "", noConflictsOrViolations, threeWayMerge, fmt.Errorf("fatal: There is no merge to abort") } - ws, err = abortMerge(ctx, ws, roots) + ws, err = merge.AbortMerge(ctx, ws, roots) if err != nil { return "", noConflictsOrViolations, threeWayMerge, err } @@ -278,43 +278,6 @@ func performMerge( return ws, commit, noConflictsOrViolations, threeWayMerge, nil } -func abortMerge(ctx *sql.Context, workingSet *doltdb.WorkingSet, roots doltdb.Roots) (*doltdb.WorkingSet, error) { - tbls, err := doltdb.UnionTableNames(ctx, roots.Working, roots.Staged, roots.Head) - if err != nil { - return nil, err - } - - roots, err = actions.MoveTablesFromHeadToWorking(ctx, roots, tbls) - if err != nil { - return nil, err - } - - preMergeWorkingRoot := workingSet.MergeState().PreMergeWorkingRoot() - preMergeWorkingTables, err := preMergeWorkingRoot.GetTableNames(ctx) - if err != nil { - return nil, err - } - nonIgnoredTables, err := doltdb.ExcludeIgnoredTables(ctx, roots, preMergeWorkingTables) - if err != nil { - return nil, err - } - someTablesAreIgnored := len(nonIgnoredTables) != len(preMergeWorkingTables) - - if someTablesAreIgnored { - newWorking, err := actions.MoveTablesBetweenRoots(ctx, nonIgnoredTables, preMergeWorkingRoot, roots.Working) - if err != nil { - return nil, err - } - workingSet = workingSet.WithWorkingRoot(newWorking) - } else { - workingSet = workingSet.WithWorkingRoot(preMergeWorkingRoot) - } - workingSet = workingSet.WithStagedRoot(workingSet.WorkingRoot()) - workingSet = workingSet.ClearMerge() - - return workingSet, nil -} - func executeMerge( ctx *sql.Context, sess *dsess.DoltSession, From 446e1acc8d12a240affbeb748bf87f9fd17d32b6 Mon Sep 17 00:00:00 2001 From: fulghum Date: Wed, 6 Dec 2023 20:16:38 +0000 Subject: [PATCH 50/63] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/libraries/events/emitter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index d8df06e976..1b78613fb8 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -32,7 +32,7 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/iohelp" ) -// Application is the application ID used for all events emitted by this application. Other applications (not dolt) +// Application is the application ID used for all events emitted by this application. Other applications (not dolt) // should set this once at initialization. var Application = eventsapi.AppID_APP_DOLT From 70b83f4ab8ce262f5acc43fd9e1dd610558dd2c0 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Wed, 6 Dec 2023 13:40:23 -0800 Subject: [PATCH 51/63] better error handling --- go/cmd/dolt/commands/version.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index 196f7a0935..cfb84d10dd 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -89,7 +89,8 @@ func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string var verr errhand.VerboseError verr = checkAndPrintVersionOutOfDateWarning(cmd.VersionStr, dEnv) if verr != nil { - return HandleVErrAndExitCode(verr, usage) + // print error but don't fail + cli.Printf("\033[33m%s\033[0m\n", verr) } if apr.Contains(verboseFlag) { @@ -156,15 +157,21 @@ func checkAndPrintVersionOutOfDateWarning(curVersion string, dEnv *env.DoltEnv) return errhand.BuildDError("error: failed to parse version check file").AddCause(err).Build() } if lastCheckDate.Before(time.Now().AddDate(0, 0, -7)) { - latestRelease, err = getLatestDoltReleaseAndRecord(path, dEnv) + latestRelease, verr = getLatestDoltReleaseAndRecord(path, dEnv) + if verr != nil { + return verr + } } } } else { - latestRelease, err = getLatestDoltReleaseAndRecord(path, dEnv) + latestRelease, verr = getLatestDoltReleaseAndRecord(path, dEnv) + if verr != nil { + return verr + } } if curVersion != latestRelease { - cli.Printf("Warning: you are on an old version of Dolt. The newest version is %s.\n", latestRelease) + cli.Printf("\033[33mWarning: you are on an old version of Dolt. The newest version is %s.\033[0m\n", latestRelease) } return nil @@ -176,7 +183,7 @@ func getLatestDoltReleaseAndRecord(path string, dEnv *env.DoltEnv) (string, errh client := github.NewClient(nil) release, resp, err := client.Repositories.GetLatestRelease(context.Background(), "dolthub", "dolt") if err != nil || resp.StatusCode != 200 { - return "", errhand.BuildDError("error: failed to get latest release").AddCause(err).Build() + return "", errhand.BuildDError("error: failed to verify latest release").AddCause(err).Build() } releaseName := strings.TrimPrefix(*release.TagName, "v") From 7bae79f00da86a69e3e19261b9710a0794249ea1 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Wed, 6 Dec 2023 14:29:23 -0800 Subject: [PATCH 52/63] Fixed license files --- go/Godeps/LICENSES | 487 +++++++++++++++++++-------------------------- go/go.mod | 2 +- 2 files changed, 211 insertions(+), 278 deletions(-) diff --git a/go/Godeps/LICENSES b/go/Godeps/LICENSES index a06b1fde17..14b08c2824 100644 --- a/go/Godeps/LICENSES +++ b/go/Godeps/LICENSES @@ -241,6 +241,215 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. = LICENSE ed6066ae50f153e2965216c6d4b9335900f1f8b2b526527f49a619d7 = ================================================================================ +================================================================================ += ./gen/proto/dolt/services/eventsapi licensed under: = + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + += LICENSE 75cd5500580317e758b5e984e017524dc961140e4889f7d427f85e41 = +================================================================================ + ================================================================================ = cloud.google.com/go licensed under: = @@ -6452,283 +6661,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------- - -Files: gzhttp/* - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016-2017 The New York Times Company - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ------------------- - -Files: s2/cmd/internal/readahead/* - -The MIT License (MIT) - -Copyright (c) 2015 Klaus Post - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ---------------------- -Files: snappy/* -Files: internal/snapref/* - -Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------------------ - -Files: s2/cmd/internal/filepathx/* - -Copyright 2016 The filepathx Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= LICENSE ab09e77acafc29821ababe88d617e81bf26ea8aa6f21f3ca9b86de18 = += LICENSE b6f05c0b9dba1bb0e91a34890d46579fbbc42d0b80de9ce3194d06f3 = ================================================================================ ================================================================================ diff --git a/go/go.mod b/go/go.mod index 04dfcf9bb7..0df0150455 100644 --- a/go/go.mod +++ b/go/go.mod @@ -113,9 +113,9 @@ require ( github.com/go-pdf/fpdf v0.6.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.11.0 // indirect From e6c4fcd3327813cb850bc3102e2fe1ce490e6db8 Mon Sep 17 00:00:00 2001 From: zachmu Date: Wed, 6 Dec 2023 22:36:44 +0000 Subject: [PATCH 53/63] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/cmd/dolt/commands/version.go | 3 ++- go/libraries/events/emitter.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index cfb84d10dd..ea337b2ef8 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -22,13 +22,14 @@ import ( "strings" "time" + "github.com/google/go-github/v57/github" + "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions" "github.com/dolthub/dolt/go/libraries/utils/argparser" - "github.com/google/go-github/v57/github" ) const ( diff --git a/go/libraries/events/emitter.go b/go/libraries/events/emitter.go index d8df06e976..1b78613fb8 100644 --- a/go/libraries/events/emitter.go +++ b/go/libraries/events/emitter.go @@ -32,7 +32,7 @@ import ( "github.com/dolthub/dolt/go/libraries/utils/iohelp" ) -// Application is the application ID used for all events emitted by this application. Other applications (not dolt) +// Application is the application ID used for all events emitted by this application. Other applications (not dolt) // should set this once at initialization. var Application = eventsapi.AppID_APP_DOLT From 0479e45377f4e9391d56fe0cbb123f1314dcfb59 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Wed, 6 Dec 2023 14:42:41 -0800 Subject: [PATCH 54/63] fix color strings --- go/cmd/dolt/commands/version.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index ea337b2ef8..563fea5e73 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -30,6 +30,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions" "github.com/dolthub/dolt/go/libraries/utils/argparser" + "github.com/fatih/color" ) const ( @@ -91,7 +92,7 @@ func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string verr = checkAndPrintVersionOutOfDateWarning(cmd.VersionStr, dEnv) if verr != nil { // print error but don't fail - cli.Printf("\033[33m%s\033[0m\n", verr) + cli.PrintErrf(color.YellowString(verr.Verbose())) } if apr.Contains(verboseFlag) { @@ -172,7 +173,7 @@ func checkAndPrintVersionOutOfDateWarning(curVersion string, dEnv *env.DoltEnv) } if curVersion != latestRelease { - cli.Printf("\033[33mWarning: you are on an old version of Dolt. The newest version is %s.\033[0m\n", latestRelease) + cli.Printf(color.YellowString("Warning: you are on an old version of Dolt. The newest version is %s.\n", latestRelease)) } return nil From ada1c646453d4ea137bdaa329582cdc55c3eb10d Mon Sep 17 00:00:00 2001 From: stephkyou Date: Wed, 6 Dec 2023 22:49:30 +0000 Subject: [PATCH 55/63] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- go/cmd/dolt/commands/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index 563fea5e73..4740e9fdcc 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -22,6 +22,7 @@ import ( "strings" "time" + "github.com/fatih/color" "github.com/google/go-github/v57/github" "github.com/dolthub/dolt/go/cmd/dolt/cli" @@ -30,7 +31,6 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/env" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dfunctions" "github.com/dolthub/dolt/go/libraries/utils/argparser" - "github.com/fatih/color" ) const ( From dccf01333b9209ea531f02eb101fb1f55e517c99 Mon Sep 17 00:00:00 2001 From: timsehn Date: Thu, 7 Dec 2023 16:54:18 +0000 Subject: [PATCH 56/63] [ga-bump-release] Update Dolt version to 1.29.1 and release v1.29.1 --- go/cmd/dolt/dolt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/cmd/dolt/dolt.go b/go/cmd/dolt/dolt.go index 732e1d6430..10c9a53cde 100644 --- a/go/cmd/dolt/dolt.go +++ b/go/cmd/dolt/dolt.go @@ -65,7 +65,7 @@ import ( ) const ( - Version = "1.29.0" + Version = "1.29.1" ) var dumpDocsCommand = &commands.DumpDocsCmd{} From 8f49d10eb0849ebf7e7a2abe6be9a34d15f1d546 Mon Sep 17 00:00:00 2001 From: James Cor Date: Thu, 7 Dec 2023 10:45:44 -0800 Subject: [PATCH 57/63] increase correctness precision (#7117) Co-authored-by: James Cor --- .../scripts/sql-correctness/get-dolt-correctness-job-json.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/sql-correctness/get-dolt-correctness-job-json.sh b/.github/scripts/sql-correctness/get-dolt-correctness-job-json.sh index 525afe75f4..d18a88c4b3 100755 --- a/.github/scripts/sql-correctness/get-dolt-correctness-job-json.sh +++ b/.github/scripts/sql-correctness/get-dolt-correctness-job-json.sh @@ -15,7 +15,7 @@ actorprefix="$5" format="$6" nomsBinFormat="$7" -precision="4" +precision="6" if [ -n "$nomsBinFormat" ]; then nomsBinFormat="\"--noms-bin-format=$nomsBinFormat\"," From 07899db4b1f3c8065e632709a134e82d1a790788 Mon Sep 17 00:00:00 2001 From: Stephanie You Date: Thu, 7 Dec 2023 11:03:55 -0800 Subject: [PATCH 58/63] fix error handling --- go/cmd/dolt/commands/version.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/go/cmd/dolt/commands/version.go b/go/cmd/dolt/commands/version.go index 4740e9fdcc..e770c88149 100644 --- a/go/cmd/dolt/commands/version.go +++ b/go/cmd/dolt/commands/version.go @@ -117,14 +117,16 @@ func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string fv, ok, err := wr.GetFeatureVersion(ctx) if err != nil { verr = errhand.BuildDError("error reading feature version").AddCause(err).Build() + return HandleVErrAndExitCode(verr, usage) } else if !ok { verr = errhand.BuildDError("the current head does not have a feature version").Build() + return HandleVErrAndExitCode(verr, usage) } else { cli.Println("feature version:", fv) } } - return HandleVErrAndExitCode(verr, usage) + return HandleVErrAndExitCode(nil, usage) } // checkAndPrintVersionOutOfDateWarning checks if the current version of Dolt is out of date and prints a warning if it From 3a226fcd83549d4b6c941bd545a4cf8e9d2ef5cc Mon Sep 17 00:00:00 2001 From: Neil Macneale IV Date: Thu, 7 Dec 2023 08:18:42 -0800 Subject: [PATCH 59/63] dolt checkout -B added. untested, existing tests pass --- go/cmd/dolt/cli/arg_parser_helpers.go | 1 + go/cmd/dolt/cli/flags.go | 1 + .../sqle/dprocedures/dolt_checkout.go | 50 +++++++++++++++---- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/go/cmd/dolt/cli/arg_parser_helpers.go b/go/cmd/dolt/cli/arg_parser_helpers.go index 7e42c95462..1fcbcacd3e 100644 --- a/go/cmd/dolt/cli/arg_parser_helpers.go +++ b/go/cmd/dolt/cli/arg_parser_helpers.go @@ -150,6 +150,7 @@ func CreateCleanArgParser() *argparser.ArgParser { func CreateCheckoutArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithVariableArgs("checkout") ap.SupportsString(CheckoutCreateBranch, "", "branch", "Create a new branch named {{.LessThan}}new_branch{{.GreaterThan}} and start it at {{.LessThan}}start_point{{.GreaterThan}}.") + ap.SupportsString(CreateResetBranch, "", "branch", "Similar to '-b'. Forcibly resets the branch to {{.LessThan}}start_point{{.GreaterThan}} if it exists.") ap.SupportsFlag(ForceFlag, "f", "If there is any changes in working set, the force flag will wipe out the current changes and checkout the new branch.") ap.SupportsString(TrackFlag, "t", "", "When creating a new branch, set up 'upstream' configuration.") return ap diff --git a/go/cmd/dolt/cli/flags.go b/go/cmd/dolt/cli/flags.go index 1fdaa1b013..92309c1dd8 100644 --- a/go/cmd/dolt/cli/flags.go +++ b/go/cmd/dolt/cli/flags.go @@ -25,6 +25,7 @@ const ( BranchParam = "branch" CachedFlag = "cached" CheckoutCreateBranch = "b" + CreateResetBranch = "B" CommitFlag = "commit" CopyFlag = "copy" DateParam = "date" diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go index 27a82ea8c9..a85456e341 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go @@ -71,9 +71,14 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes return 1, "", err } - branchOrTrack := apr.Contains(cli.CheckoutCreateBranch) || apr.Contains(cli.TrackFlag) + newBranch, _, err := parseBranchArgs(apr) + if err != nil { + return 1, "", err + } + + branchOrTrack := newBranch != "" || apr.Contains(cli.TrackFlag) if apr.Contains(cli.TrackFlag) && apr.NArg() > 0 { - return 1, "", errors.New("Improper usage.") + return 1, "", errors.New("Improper usage. Too many arguments provided.") } if (branchOrTrack && apr.NArg() > 1) || (!branchOrTrack && apr.NArg() == 0) { return 1, "", errors.New("Improper usage.") @@ -90,7 +95,7 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes if err != nil { return 1, "", err } - if apr.Contains(cli.CheckoutCreateBranch) && readOnlyDatabase { + if newBranch != "" && readOnlyDatabase { return 1, "", fmt.Errorf("unable to create new branch in a read-only database") } @@ -199,6 +204,30 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes return 0, successMessage, nil } +// parseBranchArgs returns the name of the new branch and whether or not it should be created forcibly. This asserts +// that the provided branch name may not be empty, so an empty string is returned where no -b or -B flag is provided. +func parseBranchArgs(apr *argparser.ArgParseResults) (newBranch string, createBranchForcibly bool, err error) { + if apr.Contains(cli.CheckoutCreateBranch) && apr.Contains(cli.CreateResetBranch) { + return "", false, errors.New("Improper usage. Cannot use both -b and -B.") + } + + if newBranch, ok := apr.GetValue(cli.CheckoutCreateBranch); ok { + if len(newBranch) == 0 { + return "", false, ErrEmptyBranchName + } + return newBranch, false, nil + } + + if newBranch, ok := apr.GetValue(cli.CreateResetBranch); ok { + if len(newBranch) == 0 { + return "", false, ErrEmptyBranchName + } + return newBranch, true, nil + } + + return "", false, nil +} + // isReadOnlyDatabase returns true if the named database is a read-only database. An error is returned // if any issues are encountered while looking up the named database. func isReadOnlyDatabase(ctx *sql.Context, dbName string) (bool, error) { @@ -326,6 +355,7 @@ func checkoutNewBranch(ctx *sql.Context, dbName string, dbData env.DbData, apr * var remoteName, remoteBranchName string var startPt = "head" var refSpec ref.RefSpec + var createBranchForcibly bool if apr.NArg() == 1 { startPt = apr.Arg(0) @@ -344,16 +374,14 @@ func checkoutNewBranch(ctx *sql.Context, dbName string, dbData env.DbData, apr * return "", "", err } newBranchName = remoteBranchName + } else { + // A little wonky behavior here. parseBranchArgs is actually called twice because in this procedure we pass around + // the parse results, but we also needed to parse the -b and -B flags in the main procedure. It ended up being + // a little cleaner to just call it again here than to pass the results around. + newBranchName, createBranchForcibly, err = parseBranchArgs(apr) } - if newBranch, ok := apr.GetValue(cli.CheckoutCreateBranch); ok { - if len(newBranch) == 0 { - return "", "", ErrEmptyBranchName - } - newBranchName = newBranch - } - - err = actions.CreateBranchWithStartPt(ctx, dbData, newBranchName, startPt, false, rsc) + err = actions.CreateBranchWithStartPt(ctx, dbData, newBranchName, startPt, createBranchForcibly, rsc) if err != nil { return "", "", err } From ef67ced9df66217a39a1b848a5d67b49cea3adf2 Mon Sep 17 00:00:00 2001 From: Neil Macneale IV Date: Thu, 7 Dec 2023 10:18:17 -0800 Subject: [PATCH 60/63] Added engine tests for -B flag in dolt_checkout --- .../doltcore/sqle/enginetest/dolt_queries.go | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index 57e1d2ca70..c36b9cd0a0 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -2387,6 +2387,101 @@ var DoltCheckoutScripts = []queries.ScriptTest{ }, }, }, + { + Name: "dolt_checkout with new branch forcefully", + SetUpScript: []string{ + "create table t (s varchar(5) primary key);", + "insert into t values ('foo');", + "call dolt_commit('-Am', 'commit main~2');", // will be main~2 + "insert into t values ('bar');", + "call dolt_commit('-Am', 'commit main~1');", // will be main~1 + "insert into t values ('baz');", + "call dolt_commit('-Am', 'commit main');", // will be main~1 + "call dolt_branch('testbr', 'main~1');", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "call dolt_checkout('-B', 'testbr', 'main~2');", + SkipResultsCheck: true, + }, + { + Query: "select active_branch();", + Expected: []sql.Row{{"testbr"}}, + }, + { + Query: "select * from t order by s;", + Expected: []sql.Row{{"foo"}}, + }, + { + Query: "call dolt_checkout('main');", + SkipResultsCheck: true, + }, + { + Query: "select active_branch();", + Expected: []sql.Row{{"main"}}, + }, + { + Query: "select * from t order by s;", + Expected: []sql.Row{{"bar"}, {"baz"}, {"foo"}}, + }, + { + Query: "call dolt_checkout('-B', 'testbr', 'main~1');", + SkipResultsCheck: true, + }, + { + Query: "select active_branch();", + Expected: []sql.Row{{"testbr"}}, + }, + { + Query: "select * from t order by s;", + Expected: []sql.Row{{"bar"}, {"foo"}}, + }, + }, + }, + { + Name: "dolt_checkout with new branch forcefully with dirty working set", + SetUpScript: []string{ + "create table t (s varchar(5) primary key);", + "insert into t values ('foo');", + "call dolt_commit('-Am', 'commit main~2');", // will be main~2 + "insert into t values ('bar');", + "call dolt_commit('-Am', 'commit main~1');", // will be main~1 + "insert into t values ('baz');", + "call dolt_commit('-Am', 'commit main');", // will be main~1 + "call dolt_checkout('-b', 'testbr', 'main~1');", + "insert into t values ('qux');", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "select active_branch();", + Expected: []sql.Row{{"testbr"}}, + }, + { + Query: "select * from t order by s;", + Expected: []sql.Row{{"bar"}, {"foo"}, {"qux"}}, // Dirty working set + }, + { + Query: "call dolt_checkout('main');", + SkipResultsCheck: true, + }, + { + Query: "select * from t order by s;", + Expected: []sql.Row{{"bar"}, {"baz"}, {"foo"}}, + }, + { + Query: "call dolt_checkout('-B', 'testbr', 'main~1');", + SkipResultsCheck: true, + }, + { + Query: "select active_branch();", + Expected: []sql.Row{{"testbr"}}, + }, + { + Query: "select * from t order by s;", + Expected: []sql.Row{{"bar"}, {"foo"}}, // Dirty working set was forcefully overwritten + }, + }, + }, { Name: "dolt_checkout mixed with USE statements", SetUpScript: []string{ @@ -2768,6 +2863,15 @@ var DoltCheckoutReadOnlyScripts = []queries.ScriptTest{ }, }, }, + { + Name: "dolt checkout -B returns an error for read-only databases", + Assertions: []queries.ScriptTestAssertion{ + { + Query: "call dolt_checkout('-B', 'newBranch');", + ExpectedErrStr: "unable to create new branch in a read-only database", + }, + }, + }, } var DoltInfoSchemaScripts = []queries.ScriptTest{ From 3e7f3e3542253de39749056910eec71a6fe311aa Mon Sep 17 00:00:00 2001 From: Neil Macneale IV Date: Thu, 7 Dec 2023 11:06:24 -0800 Subject: [PATCH 61/63] Add CLI support for checkout -B --- go/cmd/dolt/commands/checkout.go | 7 ++++- integration-tests/bats/checkout.bats | 40 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/go/cmd/dolt/commands/checkout.go b/go/cmd/dolt/commands/checkout.go index fb06c68937..124b929ae4 100644 --- a/go/cmd/dolt/commands/checkout.go +++ b/go/cmd/dolt/commands/checkout.go @@ -106,15 +106,20 @@ func (cmd CheckoutCmd) Exec(ctx context.Context, commandStr string, args []strin return 1 } - branchOrTrack := apr.Contains(cli.CheckoutCreateBranch) || apr.Contains(cli.TrackFlag) + // Argument validation in the CLI is strictly nice to have. The stored procedure will do the same, but the errors + // won't be as nice. + branchOrTrack := apr.Contains(cli.CheckoutCreateBranch) || apr.Contains(cli.CreateResetBranch) || apr.Contains(cli.TrackFlag) if (branchOrTrack && apr.NArg() > 1) || (!branchOrTrack && apr.NArg() == 0) { usagePrt() return 1 } + // Branch name retrieval here is strictly for messages. dolt_checkout procedure is the authority on logic around validation. var branchName string if apr.Contains(cli.CheckoutCreateBranch) { branchName, _ = apr.GetValue(cli.CheckoutCreateBranch) + } else if apr.Contains(cli.CreateResetBranch) { + branchName, _ = apr.GetValue(cli.CreateResetBranch) } else if apr.Contains(cli.TrackFlag) { if apr.NArg() > 0 { usagePrt() diff --git a/integration-tests/bats/checkout.bats b/integration-tests/bats/checkout.bats index 2b41ca0606..8062b5f921 100755 --- a/integration-tests/bats/checkout.bats +++ b/integration-tests/bats/checkout.bats @@ -314,6 +314,46 @@ SQL [[ ! "$output" =~ "4" ]] || false } +@test "checkout: -B flag will forcefully reset an existing branch" { + dolt sql -q 'create table test (id int primary key);' + dolt sql -q 'insert into test (id) values (89012);' + dolt commit -Am 'first change.' + dolt sql -q 'insert into test (id) values (76543);' + dolt commit -Am 'second change.' + + dolt checkout -b testbr main~1 + run dolt sql -q "select * from test;" + [[ "$output" =~ "89012" ]] || false + [[ ! "$output" =~ "76543" ]] || false + + # make a change to the branch which we'll lose + dolt sql -q 'insert into test (id) values (19283);' + dolt commit -Am 'change to testbr.' + + dolt checkout main + dolt checkout -B testbr main + run dolt sql -q "select * from test;" + [[ "$output" =~ "89012" ]] || false + [[ "$output" =~ "76543" ]] || false + [[ ! "$output" =~ "19283" ]] || false +} + +@test "checkout: -B will create a branch that does not exist" { + dolt sql -q 'create table test (id int primary key);' + dolt sql -q 'insert into test (id) values (89012);' + dolt commit -Am 'first change.' + dolt sql -q 'insert into test (id) values (76543);' + dolt commit -Am 'second change.' + + dolt checkout -B testbr main~1 + run dolt sql -q "select * from test;" + [[ "$output" =~ "89012" ]] || false + [[ ! "$output" =~ "76543" ]] || false +} + + + + @test "checkout: attempting to checkout a detached head shows a suggestion instead" { dolt sql -q "create table test (id int primary key);" dolt add . From 02d11b98d1ff305a75ee3e1277a0ccd2794f982b Mon Sep 17 00:00:00 2001 From: Neil Macneale IV Date: Thu, 7 Dec 2023 13:03:13 -0800 Subject: [PATCH 62/63] Fix logical mistake on -t and -b being exclusive --- .../sqle/dprocedures/dolt_checkout.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go index a85456e341..4eaff0a55b 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go @@ -355,7 +355,6 @@ func checkoutNewBranch(ctx *sql.Context, dbName string, dbData env.DbData, apr * var remoteName, remoteBranchName string var startPt = "head" var refSpec ref.RefSpec - var createBranchForcibly bool if apr.NArg() == 1 { startPt = apr.Arg(0) @@ -374,11 +373,19 @@ func checkoutNewBranch(ctx *sql.Context, dbName string, dbData env.DbData, apr * return "", "", err } newBranchName = remoteBranchName - } else { - // A little wonky behavior here. parseBranchArgs is actually called twice because in this procedure we pass around - // the parse results, but we also needed to parse the -b and -B flags in the main procedure. It ended up being - // a little cleaner to just call it again here than to pass the results around. - newBranchName, createBranchForcibly, err = parseBranchArgs(apr) + } + + // A little wonky behavior here. parseBranchArgs is actually called twice because in this procedure we pass around + // the parse results, but we also needed to parse the -b and -B flags in the main procedure. It ended up being + // a little cleaner to just call it again here than to pass the results around. + var createBranchForcibly bool + var optionBBranch string + optionBBranch, createBranchForcibly, err = parseBranchArgs(apr) + if err != nil { + return "", "", err + } + if optionBBranch != "" { + newBranchName = optionBBranch } err = actions.CreateBranchWithStartPt(ctx, dbData, newBranchName, startPt, createBranchForcibly, rsc) From 80037bcffcdd9afcd79842e29e726278b9f4c8eb Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Thu, 7 Dec 2023 13:33:07 -0800 Subject: [PATCH 63/63] [auto-bump] [no-release-notes] dependency by jennifersp (#7112) --- go/Godeps/LICENSES | 29 ------------------- go/go.mod | 4 +-- go/go.sum | 8 ++--- .../sqle/enginetest/dolt_engine_test.go | 8 ++--- .../node/workbenchTests/diffs.js | 2 +- .../node/workbenchTests/views.js | 2 +- 6 files changed, 12 insertions(+), 41 deletions(-) diff --git a/go/Godeps/LICENSES b/go/Godeps/LICENSES index 14b08c2824..281317ef2f 100644 --- a/go/Godeps/LICENSES +++ b/go/Godeps/LICENSES @@ -1996,35 +1996,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. = LICENSE 3f09359866e587619921288cca4607374451bbd3b3f3806bc70598b6 = ================================================================================ -================================================================================ -= github.com/cespare/xxhash licensed under: = - -Copyright (c) 2016 Caleb Spare - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -= LICENSE.txt 726f1b8f64f7e439b1b12c7cbde7b1427752a00ddea15019e4156465 = -================================================================================ - ================================================================================ = github.com/cespare/xxhash/v2 licensed under: = diff --git a/go/go.mod b/go/go.mod index 0df0150455..a14360282b 100644 --- a/go/go.mod +++ b/go/go.mod @@ -15,7 +15,7 @@ require ( github.com/dolthub/fslock v0.0.3 github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488 github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 - github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f + github.com/dolthub/vitess v0.0.0-20231207010700-88fb35413580 github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.13.0 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 @@ -57,7 +57,7 @@ require ( github.com/cespare/xxhash v1.1.0 github.com/creasty/defaults v1.6.0 github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 - github.com/dolthub/go-mysql-server v0.17.1-0.20231205222834-2eb85072ed9d + github.com/dolthub/go-mysql-server v0.17.1-0.20231207014254-4bbb22ce2d4d github.com/dolthub/swiss v0.1.0 github.com/goccy/go-json v0.10.2 github.com/google/go-github/v57 v57.0.0 diff --git a/go/go.sum b/go/go.sum index e8c8f85079..25173dc25a 100644 --- a/go/go.sum +++ b/go/go.sum @@ -181,8 +181,8 @@ github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U= github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0= github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e h1:kPsT4a47cw1+y/N5SSCkma7FhAPw7KeGmD6c9PBZW9Y= github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e/go.mod h1:KPUcpx070QOfJK1gNe0zx4pA5sicIK1GMikIGLKC168= -github.com/dolthub/go-mysql-server v0.17.1-0.20231205222834-2eb85072ed9d h1:DBMlz2ONWPx6qZhUps8qwlvGa2QwsDSBKbOHxhr55Gc= -github.com/dolthub/go-mysql-server v0.17.1-0.20231205222834-2eb85072ed9d/go.mod h1:vXlRKS39WHav9N51VsfYphKhmSA2t5FkhHmW3BtwH5I= +github.com/dolthub/go-mysql-server v0.17.1-0.20231207014254-4bbb22ce2d4d h1:qesX3+3ll8CiqUbCXYxHemsC6q2i6lxIs9fkYX+8i/g= +github.com/dolthub/go-mysql-server v0.17.1-0.20231207014254-4bbb22ce2d4d/go.mod h1:zJCyPiYe9VZ9xIQTv7S1OFKwyoVQoeGxZXNtkFxTcOI= github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488 h1:0HHu0GWJH0N6a6keStrHhUAK5/o9LVfkh44pvsV4514= github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488/go.mod h1:ehexgi1mPxRTk0Mok/pADALuHbvATulTh6gzr7NzZto= github.com/dolthub/jsonpath v0.0.2-0.20230525180605-8dc13778fd72 h1:NfWmngMi1CYUWU4Ix8wM+USEhjc+mhPlT9JUR/anvbQ= @@ -193,8 +193,8 @@ github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 h1:7/v8q9X github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81/go.mod h1:siLfyv2c92W1eN/R4QqG/+RjjX5W2+gCTRjZxBjI3TY= github.com/dolthub/swiss v0.1.0 h1:EaGQct3AqeP/MjASHLiH6i4TAmgbG/c4rA6a1bzCOPc= github.com/dolthub/swiss v0.1.0/go.mod h1:BeucyB08Vb1G9tumVN3Vp/pyY4AMUnr9p7Rz7wJ7kAQ= -github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f h1:I480LKHhb4usnF3dYhp6J4ORKMrncNKaWYZvIZwlK+U= -github.com/dolthub/vitess v0.0.0-20231127171856-2466012fb61f/go.mod h1:IwjNXSQPymrja5pVqmfnYdcy7Uv7eNJNBPK/MEh9OOw= +github.com/dolthub/vitess v0.0.0-20231207010700-88fb35413580 h1:OSp1g3tRBMVIyxza4LN20rZ6yYEKqjf5hNNisVg/Lns= +github.com/dolthub/vitess v0.0.0-20231207010700-88fb35413580/go.mod h1:IwjNXSQPymrja5pVqmfnYdcy7Uv7eNJNBPK/MEh9OOw= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 71d0a9f8be..7005429dfb 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -89,7 +89,7 @@ func TestSingleQuery(t *testing.T) { } for _, q := range setupQueries { - enginetest.RunQuery(t, engine, harness, q) + enginetest.RunQueryWithContext(t, engine, harness, nil, q) } // engine.EngineAnalyzer().Debug = true @@ -331,7 +331,7 @@ func TestSingleQueryPrepared(t *testing.T) { } for _, q := range setupQueries { - enginetest.RunQuery(t, engine, harness, q) + enginetest.RunQueryWithContext(t, engine, harness, nil, q) } //engine.Analyzer.Debug = true @@ -2340,7 +2340,7 @@ func TestSystemTableIndexes(t *testing.T) { ctx := enginetest.NewContext(harness) for _, q := range stt.setup { - enginetest.RunQuery(t, e, harness, q) + enginetest.RunQueryWithContext(t, e, harness, ctx, q) } for i, c := range []string{"inner", "lookup", "hash", "merge"} { @@ -2375,7 +2375,7 @@ func TestSystemTableIndexesPrepared(t *testing.T) { ctx := enginetest.NewContext(harness) for _, q := range stt.setup { - enginetest.RunQuery(t, e, harness, q) + enginetest.RunQueryWithContext(t, e, harness, ctx, q) } for _, tt := range stt.queries { diff --git a/integration-tests/mysql-client-tests/node/workbenchTests/diffs.js b/integration-tests/mysql-client-tests/node/workbenchTests/diffs.js index 087855c59d..daa22bbdf4 100644 --- a/integration-tests/mysql-client-tests/node/workbenchTests/diffs.js +++ b/integration-tests/mysql-client-tests/node/workbenchTests/diffs.js @@ -197,7 +197,7 @@ export const diffTests = [ to_name: "myview", to_fragment: "CREATE VIEW `myview` AS SELECT * FROM test", to_extra: { CreatedAt: 0 }, - to_sql_mode: 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY', + to_sql_mode: 'NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES', to_commit: "WORKING", to_commit_date: "2023-03-09T07:56:29.035Z", from_type: null, diff --git a/integration-tests/mysql-client-tests/node/workbenchTests/views.js b/integration-tests/mysql-client-tests/node/workbenchTests/views.js index 49370d4cdb..4a0aab1646 100644 --- a/integration-tests/mysql-client-tests/node/workbenchTests/views.js +++ b/integration-tests/mysql-client-tests/node/workbenchTests/views.js @@ -34,7 +34,7 @@ export const viewsTests = [ name: "myview", fragment: "CREATE VIEW `myview` AS SELECT * FROM test", extra: { CreatedAt: 0 }, - sql_mode: 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY', + sql_mode: 'NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES', }, ], },