Skip to content

Commit 36fcc63

Browse files
authored
Merge pull request #10104 from dolthub/elian/1374
Add separate author and committer support
2 parents 7393633 + 4c1fbc8 commit 36fcc63

96 files changed

Lines changed: 1984 additions & 685 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-compatibility-tests.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ jobs:
3030
- uses: actions/setup-node@v4
3131
with:
3232
node-version: ^16
33+
- name: Install netcat
34+
run: sudo apt-get update && sudo apt-get install -y netcat-openbsd
3335
- name: Create CI Bin
3436
run: |
3537
mkdir -p ./.ci_bin

go/cmd/dolt/commands/assist.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ func getInitialPrompt(ctx *sql.Context, sqlEngine *engine.SqlEngine, dEnv *env.D
498498
return nil, err
499499
}
500500

501-
responseJson, err = json.Marshal(map[string]string{"action": "ANSWER", "content": fmt.Sprintf("The most recent commit was written by %s", cm.Name)})
501+
responseJson, err = json.Marshal(map[string]string{"action": "ANSWER", "content": fmt.Sprintf("The most recent commit was written by %s", cm.Author.Name)})
502502
if err != nil {
503503
return nil, err
504504
}

go/cmd/dolt/commands/commit.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ func performCommit(ctx context.Context, commandStr string, args []string, cliCtx
174174
}
175175

176176
commit, err := getCommitInfo(queryist.Context, queryist.Queryist, "HEAD")
177+
if err != nil {
178+
cli.Printf("Commit completed, but failure to get commit details occurred: %s\n", err.Error())
179+
return 0, false
180+
}
177181
if cli.ExecuteWithStdioRestored != nil {
178182
cli.ExecuteWithStdioRestored(func() {
179183
pager := outputpager.Start()
@@ -235,20 +239,15 @@ func constructParametrizedDoltCommitQuery(msg string, apr *argparser.ArgParseRes
235239
writeToBuffer("-f")
236240
}
237241

238-
writeToBuffer("--author")
239-
param = true
240-
writeToBuffer("?")
241-
var author string
242242
if apr.Contains(cli.AuthorParam) {
243-
author, _ = apr.GetValue(cli.AuthorParam)
244-
} else {
245-
name, email, err := env.GetNameAndEmail(cliCtx.Config())
246-
if err != nil {
247-
return "", nil, err
248-
}
249-
author = name + " <" + email + ">"
243+
writeToBuffer("--author")
244+
param = true
245+
writeToBuffer("?")
246+
author, _ := apr.GetValue(cli.AuthorParam)
247+
params = append(params, author)
248+
} else if _, _, err := env.GetNameAndEmail(cliCtx.Config()); err != nil {
249+
return "", nil, err
250250
}
251-
params = append(params, author)
252251

253252
if apr.Contains(cli.AllFlag) {
254253
writeToBuffer("-a")
@@ -291,15 +290,15 @@ func handleCommitErr(sqlCtx *sql.Context, queryist cli.Queryist, err error, usag
291290
return 0
292291
}
293292

294-
if err == datas.ErrNameNotConfigured {
293+
if datas.ErrNameNotConfigured.Is(err) {
295294
bdr := errhand.BuildDError("Could not determine %s.", config.UserNameKey)
296295
bdr.AddDetails("Log into DoltHub: dolt login")
297296
bdr.AddDetails("OR add name to config: dolt config [--global|--local] --add %[1]s \"FIRST LAST\"", config.UserNameKey)
298297

299298
return HandleVErrAndExitCode(bdr.Build(), usage)
300299
}
301300

302-
if err == datas.ErrEmailNotConfigured {
301+
if datas.ErrEmailNotConfigured.Is(err) {
303302
bdr := errhand.BuildDError("Could not determine %s.", config.UserEmailKey)
304303
bdr.AddDetails("Log into DoltHub: dolt login")
305304
bdr.AddDetails("OR add email to config: dolt config [--global|--local] --add %[1]s \"EMAIL_ADDRESS\"", config.UserEmailKey)

go/cmd/dolt/commands/engine/sqlengine.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package engine
1616

1717
import (
1818
"context"
19+
"fmt"
1920
"maps"
2021
"os"
2122
"strconv"
@@ -595,6 +596,96 @@ func doltSessionFactory(
595596
}
596597
}
597598

599+
var ErrFailedToInitCommitIdent = fmt.Errorf("failed to initialize commit identity session variables from environment")
600+
601+
// envSessionVar pairs an environment variable with the session variable it populates when non-empty.
602+
type envSessionVar struct {
603+
envVar string
604+
sessionVar string
605+
}
606+
607+
// commitIdentEnvOverrides lists the DOLT_AUTHOR_* and DOLT_COMMITTER_* environment variables
608+
// that [InitClientCommitIdentSession] maps to their corresponding session variables.
609+
var commitIdentEnvOverrides = []envSessionVar{
610+
{dconfig.EnvDoltAuthorName, dsess.DoltAuthorName},
611+
{dconfig.EnvDoltAuthorEmail, dsess.DoltAuthorEmail},
612+
{dconfig.EnvDoltAuthorDate, dsess.DoltAuthorDate},
613+
{dconfig.EnvDoltCommitterName, dsess.DoltCommitterName},
614+
{dconfig.EnvDoltCommitterEmail, dsess.DoltCommitterEmail},
615+
{dconfig.EnvDoltCommitterDate, dsess.DoltCommitterDate},
616+
}
617+
618+
// InitClientCommitIdentSession seeds the DOLT_ author and committer session variables on the
619+
// dolt CLI client's session so later DOLT_COMMIT calls attribute the commit correctly. |name|
620+
// and |email| supply the default identity for both author and committer; any non-empty
621+
// DOLT_AUTHOR_* or DOLT_COMMITTER_* environment variable overrides the matching field. Must run
622+
// after [sql.SessionCommandBegin] so the session is ready to accept SET statements. Silently
623+
// skips variables not recognised by |queryist|, so older servers remain usable.
624+
func InitClientCommitIdentSession(queryist cli.Queryist, sqlCtx *sql.Context, name, email string) error {
625+
sessionVars := map[string]string{
626+
dsess.DoltAuthorName: name,
627+
dsess.DoltAuthorEmail: email,
628+
dsess.DoltCommitterName: name,
629+
dsess.DoltCommitterEmail: email,
630+
}
631+
632+
for _, pair := range commitIdentEnvOverrides {
633+
if val := os.Getenv(pair.envVar); val != "" {
634+
sessionVars[pair.sessionVar] = val
635+
}
636+
}
637+
638+
var showQuery strings.Builder
639+
showQuery.WriteString("SHOW VARIABLES WHERE Variable_name IN (")
640+
hasVariableNames := false
641+
for variableName, value := range sessionVars {
642+
if value == "" {
643+
continue
644+
}
645+
if hasVariableNames {
646+
showQuery.WriteByte(',')
647+
}
648+
showQuery.WriteByte('\'')
649+
showQuery.WriteString(variableName)
650+
showQuery.WriteByte('\'')
651+
hasVariableNames = true
652+
}
653+
if !hasVariableNames {
654+
return nil
655+
}
656+
showQuery.WriteByte(')')
657+
variableRows, err := cli.GetRowsForSql(queryist, sqlCtx, showQuery.String())
658+
if err != nil {
659+
return fmt.Errorf("%w: %v", ErrFailedToInitCommitIdent, err)
660+
}
661+
662+
var setStatement strings.Builder
663+
setStatement.WriteString("SET ")
664+
hasAssignments := false
665+
for _, row := range variableRows {
666+
variableName, ok := row[0].(string)
667+
if !ok {
668+
continue
669+
}
670+
value, ok := sessionVars[strings.ToLower(variableName)]
671+
if !ok {
672+
continue
673+
}
674+
if hasAssignments {
675+
setStatement.WriteString(", ")
676+
}
677+
fmt.Fprintf(&setStatement, "@@SESSION.%s = %q", variableName, value)
678+
hasAssignments = true
679+
}
680+
if !hasAssignments {
681+
return nil
682+
}
683+
if _, _, _, err := queryist.Query(sqlCtx, setStatement.String()); err != nil {
684+
return fmt.Errorf("%w: %v", ErrFailedToInitCommitIdent, err)
685+
}
686+
return nil
687+
}
688+
598689
type ConfigOption func(*SqlEngineConfig)
599690

600691
// NewSqlEngineForEnv returns a SqlEngine configured for the environment provided, with a single root user.

go/cmd/dolt/commands/log_graph.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ func printCommitMetadata(graph [][]string, pager *outputpager.Pager, row, col in
344344
printLine(graph, col, row+1, pager, color.WhiteString("Merge: %s", strings.Join(commit.Commit.parentHashes, " ")), commit.Commit, "no")
345345
}
346346

347-
printLine(graph, col, row+1+printMergeInfo, pager, color.WhiteString("Author: %s <%s>", commit.Commit.commitMeta.Name, commit.Commit.commitMeta.Email), commit.Commit, "no")
347+
printLine(graph, col, row+1+printMergeInfo, pager, color.WhiteString("Author: %s <%s>", commit.Commit.commitMeta.Author.Name, commit.Commit.commitMeta.Author.Email), commit.Commit, "no")
348348

349349
printLine(graph, col, row+2+printMergeInfo, pager, color.WhiteString("Date: %s", commit.Commit.commitMeta.FormatTS()), commit.Commit, "no")
350350

go/cmd/dolt/commands/log_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func TestLog(t *testing.T) {
4646
commit, _ := opt.ToCommit()
4747

4848
meta, _ := commit.GetCommitMeta(context.Background())
49-
require.Equal(t, "Bill Billerson", meta.Name)
49+
require.Equal(t, "Bill Billerson", meta.Author.Name)
5050
}
5151

5252
func TestLogSigterm(t *testing.T) {
@@ -79,7 +79,7 @@ func TestLogSigterm(t *testing.T) {
7979

8080
for i := 0; i < 5; i++ {
8181
pager.Writer.Write([]byte(fmt.Sprintf("\033[1;33mcommit %s \033[0m", chStr)))
82-
pager.Writer.Write([]byte(fmt.Sprintf("\nAuthor: %s <%s>", cMeta.Name, cMeta.Email)))
82+
pager.Writer.Write([]byte(fmt.Sprintf("\nAuthor: %s <%s>", cMeta.Author.Name, cMeta.Author.Email)))
8383

8484
timeStr := cMeta.FormatTS()
8585
pager.Writer.Write([]byte(fmt.Sprintf("\nDate: %s", timeStr)))

go/cmd/dolt/commands/schcmds/copy-tags.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
3232
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
3333
"github.com/dolthub/dolt/go/libraries/utils/argparser"
34-
"github.com/dolthub/dolt/go/libraries/utils/config"
3534
"github.com/dolthub/dolt/go/store/datas"
3635
)
3736

@@ -272,22 +271,13 @@ func doltCommitUpdatedTags(ctx *sql.Context, tableResolver doltdb.TableResolver,
272271
workingSet = workingSet.WithWorkingRoot(workingRoot)
273272
workingSet = workingSet.WithStagedRoot(workingRoot)
274273

275-
email, err := dEnv.Config.GetString(config.UserEmailKey)
276-
if err != nil {
277-
return err
278-
}
279-
280-
name, err := dEnv.Config.GetString(config.UserNameKey)
274+
doltDB := dEnv.DoltDB(ctx)
275+
commitStagedProps, _, err := dsess.NewCommitStagedProps(ctx, "Syncing column tags from "+fromBranchName+" branch")
281276
if err != nil {
282277
return err
283278
}
284279

285-
doltDB := dEnv.DoltDB(ctx)
286-
pendingCommit, err := actions.GetCommitStaged(ctx, tableResolver, roots, workingSet, nil, doltDB, actions.CommitStagedProps{
287-
Name: name,
288-
Email: email,
289-
Message: "Syncing column tags from " + fromBranchName + " branch",
290-
})
280+
pendingCommit, err := actions.GetCommitStaged(ctx, tableResolver, roots, workingSet, nil, doltDB, commitStagedProps)
291281
if err != nil {
292282
return err
293283
}
@@ -302,8 +292,8 @@ func doltCommitUpdatedTags(ctx *sql.Context, tableResolver doltdb.TableResolver,
302292
}
303293

304294
_, err = doltDB.CommitWithWorkingSet(ctx, headRef, workingSet.Ref(), pendingCommit, workingSet, prevHash, &datas.WorkingSetMeta{
305-
Name: name,
306-
Email: email,
295+
Name: commitStagedProps.Committer.Name,
296+
Email: commitStagedProps.Committer.Email,
307297
}, nil)
308298
return err
309299
}

go/cmd/dolt/commands/sqlserver/queryist_utils.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
sql2 "database/sql"
2121
"fmt"
2222
"io"
23+
"net"
2324
"regexp"
2425
"strings"
2526

@@ -30,6 +31,7 @@ import (
3031
"github.com/gocraft/dbr/v2/dialect"
3132

3233
"github.com/dolthub/dolt/go/cmd/dolt/cli"
34+
"github.com/dolthub/dolt/go/cmd/dolt/commands/engine"
3335
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
3436
"github.com/dolthub/dolt/go/libraries/doltcore/servercfg"
3537
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil"
@@ -61,9 +63,12 @@ const (
6163
QueryistTLSMode_NoVerify_FallbackToPlaintext
6264
)
6365

64-
// BuildConnectionStringQueryist returns a Queryist that connects to the server specified by the given server config. Presence in this
65-
// module isn't ideal, but it's the only way to get the server config into the queryist.
66-
func BuildConnectionStringQueryist(ctx context.Context, cwdFS filesys.Filesys, creds *cli.UserPassword, apr *argparser.ArgParseResults, host string, port int, tlsMode QueryistTLSMode, dbRev string) (cli.LateBindQueryist, error) {
66+
// BuildConnectionStringQueryist returns a [cli.LateBindQueryist] that opens a connection to the
67+
// server at |host|:|port| using |creds| and |tlsMode|, and selects |dbRev| as the default
68+
// database. |configName| and |configEmail| are used as the commit identity when the client
69+
// connects over a loopback address; non-loopback connections read the identity from
70+
// CURRENT_USER() so the grant host matches whatever the server assigned.
71+
func BuildConnectionStringQueryist(_ context.Context, cwdFS filesys.Filesys, creds *cli.UserPassword, apr *argparser.ArgParseResults, host string, port int, tlsMode QueryistTLSMode, dbRev string, configName, configEmail string) (cli.LateBindQueryist, error) {
6772
clientConfig, err := GetClientConfig(cwdFS, creds, apr)
6873
if err != nil {
6974
return nil, err
@@ -101,6 +106,14 @@ func BuildConnectionStringQueryist(ctx context.Context, cwdFS filesys.Filesys, c
101106
var lateBind cli.LateBindQueryist = func(ctx context.Context, opts ...cli.LateBindQueryistOption) (res cli.LateBindQueryistResult, err error) {
102107
sqlCtx := sql.NewContext(ctx)
103108
sqlCtx.SetCurrentDatabase(dbRev)
109+
110+
ip := net.ParseIP(host)
111+
if host == "localhost" || (ip != nil && ip.IsLoopback()) {
112+
if err := engine.InitClientCommitIdentSession(queryist, sqlCtx, configName, configEmail); err != nil {
113+
cli.PrintErr(err.Error())
114+
}
115+
}
116+
104117
res.Queryist = queryist
105118
res.Context = sqlCtx
106119
res.Closer = func() {

go/cmd/dolt/commands/sqlserver/server.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,27 +1181,26 @@ func newSessionBuilder(se *engine.SqlEngine, config servercfg.ServerConfig) serv
11811181
return nil, err
11821182
}
11831183

1184-
dsess, err := se.NewDoltSession(ctx, baseSession)
1184+
dSess, err := se.NewDoltSession(ctx, baseSession)
11851185
if err != nil {
11861186
return nil, err
11871187
}
11881188

11891189
varsForUser := userToSessionVars[conn.User]
11901190
if len(varsForUser) > 0 {
1191-
sqlCtx, err := se.NewContext(ctx, dsess)
1191+
sqlCtx, err := se.NewContext(ctx, dSess)
11921192
if err != nil {
11931193
return nil, err
11941194
}
11951195

11961196
for key, val := range varsForUser {
1197-
err = dsess.InitSessionVariable(sqlCtx, key, val)
1198-
if err != nil {
1197+
if err = dSess.InitSessionVariable(sqlCtx, key, val); err != nil {
11991198
return nil, err
12001199
}
12011200
}
12021201
}
12031202

1204-
return dsess, nil
1203+
return dSess, nil
12051204
}
12061205
}
12071206

0 commit comments

Comments
 (0)