diff --git a/go/cmd/dolt/commands/commit.go b/go/cmd/dolt/commands/commit.go index 6866ceaf2d..bf7899164f 100644 --- a/go/cmd/dolt/commands/commit.go +++ b/go/cmd/dolt/commands/commit.go @@ -40,7 +40,7 @@ import ( ) var commitDocs = cli.CommandDocumentationContent{ - ShortDesc: "Record changes to the repository", + ShortDesc: "Record changes to the database", LongDesc: ` Stores the current contents of the staged tables in a new commit along with a log message from the user describing the changes. diff --git a/go/cmd/dolt/commands/log.go b/go/cmd/dolt/commands/log.go index 4d1799dcfd..69a5d5eea8 100644 --- a/go/cmd/dolt/commands/log.go +++ b/go/cmd/dolt/commands/log.go @@ -36,14 +36,14 @@ import ( ) type logOpts struct { - numLines int - showParents bool - minParents int - decoration string - oneLine bool - excludingCommitSpec *doltdb.CommitSpec - commitSpec *doltdb.CommitSpec - tableName string + numLines int + showParents bool + minParents int + decoration string + oneLine bool + excludingCommitSpecs []*doltdb.CommitSpec + commitSpecs []*doltdb.CommitSpec + tableName string } type logNode struct { @@ -114,17 +114,12 @@ func (cmd LogCmd) logWithLoggerFunc(ctx context.Context, commandStr string, args help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, logDocs, ap)) apr := cli.ParseArgsOrDie(ap, args, help) - if apr.NArg() > 2 { - usage() - return 1 - } - opts, err := parseLogArgs(ctx, dEnv, apr) if err != nil { return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage) } - if opts.commitSpec == nil { - opts.commitSpec = dEnv.RepoStateReader().CWBHeadSpec() + if len(opts.commitSpecs) == 0 { + opts.commitSpecs = append(opts.commitSpecs, dEnv.RepoStateReader().CWBHeadSpec()) } if len(opts.tableName) > 0 { return handleErrAndExit(logTableCommits(ctx, dEnv, opts)) @@ -152,146 +147,95 @@ func parseLogArgs(ctx context.Context, dEnv *env.DoltEnv, apr *argparser.ArgPars oneLine: apr.Contains(cli.OneLineFlag), decoration: decorateOption, } - cs, notCs, tableName, err := parseRefsAndTable(ctx, apr, dEnv) + + err := opts.parseRefsAndTable(ctx, apr, dEnv) if err != nil { return nil, err } - opts.commitSpec = cs - opts.excludingCommitSpec = notCs - opts.tableName = tableName excludingRef, ok := apr.GetValue(cli.NotFlag) if ok { - if opts.excludingCommitSpec != nil { + if len(opts.excludingCommitSpecs) > 0 { return nil, fmt.Errorf("cannot use --not argument with two dots or ref with ^") } if len(opts.tableName) > 0 { return nil, fmt.Errorf("cannot use --not argument with table") } - cs, err := doltdb.NewCommitSpec(excludingRef) + notCs, err := doltdb.NewCommitSpec(excludingRef) if err != nil { return nil, fmt.Errorf("invalid commit %s\n", excludingRef) } - opts.excludingCommitSpec = cs + opts.excludingCommitSpecs = append(opts.excludingCommitSpecs, notCs) } return opts, nil } -func parseRefsAndTable(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv) (*doltdb.CommitSpec, *doltdb.CommitSpec, string, error) { - switch apr.NArg() { - // dolt log - case 0: - return nil, nil, "", nil - - // dolt log - case 1: - return getCommitOrTableFromString(ctx, apr.Arg(0), dEnv, true) - - // dolt log - case 2: - firstCs, firstExNotCs, _, err := getCommitOrTableFromString(ctx, apr.Arg(0), dEnv, false) - if err != nil { - return nil, nil, "", err - } - - secondCs, secondExNotCs, tableName, err := getCommitOrTableFromString(ctx, apr.Arg(1), dEnv, false) - if err != nil { - return nil, nil, "", err - } - - if len(tableName) > 0 { - if firstExNotCs != nil { - return nil, nil, "", fmt.Errorf("Providing tableName for two dot log not yet supported") - } - // dolt log - return firstCs, nil, tableName, nil - } - - if firstCs != nil && secondCs != nil { - commit, err := dEnv.DoltDB.Resolve(ctx, firstCs, dEnv.RepoStateReader().CWBHeadRef()) - if err != nil { - return nil, nil, "", err - } - - // Handles table name matching branch name (dolt log
) - exists, err := tableExists(ctx, commit, apr.Arg(1)) - if err != nil { - return nil, nil, "", err - } - - if exists { - return firstCs, nil, apr.Arg(1), nil - } - - return nil, nil, "", fmt.Errorf("Cannot provide two commit refs") // dolt log - } - if firstExNotCs != nil && secondExNotCs != nil { - return nil, nil, "", fmt.Errorf("Cannot exclude two commit refs") // dolt log ^ ^ - } - // dolt log ^ - if firstExNotCs != nil && secondCs != nil { - return secondCs, firstExNotCs, "", nil - } - // dolt log ^ - if firstCs != nil && secondExNotCs != nil { - return firstCs, secondExNotCs, "", nil - } - - return nil, nil, "", nil - - default: - return nil, nil, "", fmt.Errorf("Cannot provide more than 3 arguments") - } -} - -func getCommitOrTableFromString(ctx context.Context, str string, dEnv *env.DoltEnv, canDot bool) (*doltdb.CommitSpec, *doltdb.CommitSpec, string, error) { - // ... - if strings.Contains(str, "...") { - return nil, nil, "", fmt.Errorf("Three dot dolt log not supported") +func (opts *logOpts) parseRefsAndTable(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEnv) error { + // `dolt log` + if apr.NArg() == 0 { + return nil } - // .. - if strings.Contains(str, "..") { - if !canDot { - return nil, nil, "", fmt.Errorf("Cannot use two dot when 2 arguments provided") + // `dolt log ..` + if strings.Contains(apr.Arg(0), "..") { + if strings.Contains(apr.Arg(0), "...") { + return fmt.Errorf("three dot log not yet supported") } - refs := strings.Split(str, "..") + if apr.NArg() > 1 { + return fmt.Errorf("Cannot use two dot when 2 or more arguments provided") + } + refs := strings.Split(apr.Arg(0), "..") notCs, err := getCommitSpec(refs[0]) if err != nil { - return nil, nil, "", err + return err } cs, err := getCommitSpec(refs[1]) if err != nil { - return nil, nil, "", err + return err } - return cs, notCs, "", nil + opts.commitSpecs = append(opts.commitSpecs, cs) + opts.excludingCommitSpecs = append(opts.excludingCommitSpecs, notCs) + + return nil } - // ^ - if strings.HasPrefix(str, "^") { - commit := strings.TrimPrefix(str, "^") - notCs, err := getCommitSpec(commit) - if err != nil { - return nil, nil, "", err + seenRefs := make(map[string]bool) + + for _, arg := range apr.Args { + // ^ + if strings.HasPrefix(arg, "^") { + commit := strings.TrimPrefix(arg, "^") + notCs, err := getCommitSpec(commit) + if err != nil { + return err + } + + opts.excludingCommitSpecs = append(opts.excludingCommitSpecs, notCs) + } else { + argIsRef := actions.ValidateIsRef(ctx, arg, dEnv.DoltDB, dEnv.RepoStateReader()) + // + if argIsRef && !seenRefs[arg] { + cs, err := getCommitSpec(arg) + if err != nil { + return err + } + seenRefs[arg] = true + opts.commitSpecs = append(opts.commitSpecs, cs) + } else { + //
+ opts.tableName = arg + } } - return nil, notCs, "", err } - argIsRef := actions.ValidateIsRef(ctx, str, dEnv.DoltDB, dEnv.RepoStateReader()) - // - if argIsRef { - cs, err := getCommitSpec(str) - if err != nil { - return nil, nil, "", err - } - return cs, nil, "", nil + if len(opts.tableName) > 0 && len(opts.excludingCommitSpecs) > 0 { + return fmt.Errorf("Cannot provide table name with excluding refs") } - //
- return nil, nil, str, nil + return nil } func getCommitSpec(commit string) (*doltdb.CommitSpec, error) { @@ -303,10 +247,22 @@ func getCommitSpec(commit string) (*doltdb.CommitSpec, error) { } func logCommits(ctx context.Context, dEnv *env.DoltEnv, opts *logOpts) int { - commit, err := dEnv.DoltDB.Resolve(ctx, opts.commitSpec, dEnv.RepoStateReader().CWBHeadRef()) - if err != nil { - cli.PrintErrln(color.HiRedString("Fatal error: cannot get HEAD commit for current branch.")) - return 1 + hashes := make([]hash.Hash, len(opts.commitSpecs)) + + for i, cs := range opts.commitSpecs { + commit, err := dEnv.DoltDB.Resolve(ctx, cs, dEnv.RepoStateReader().CWBHeadRef()) + if err != nil { + cli.PrintErrln(color.HiRedString("Fatal error: cannot get HEAD commit for current branch.")) + return 1 + } + + h, err := commit.HashOf() + if err != nil { + cli.PrintErrln(color.HiRedString("Fatal error: failed to get commit hash")) + return 1 + } + + hashes[i] = h } cHashToRefs := map[hash.Hash][]string{} @@ -356,39 +312,37 @@ func logCommits(ctx context.Context, dEnv *env.DoltEnv, opts *logOpts) int { cHashToRefs[t.Hash] = append(cHashToRefs[t.Hash], tagName) } - h, err := commit.HashOf() - - if err != nil { - cli.PrintErrln(color.HiRedString("Fatal error: failed to get commit hash")) - return 1 - } - - matchFunc := func(commit *doltdb.Commit) (bool, error) { - return commit.NumParents() >= opts.minParents, nil + matchFunc := func(c *doltdb.Commit) (bool, error) { + return c.NumParents() >= opts.minParents, nil } var commits []*doltdb.Commit - if opts.excludingCommitSpec == nil { - commits, err = commitwalk.GetTopNTopoOrderedCommitsMatching(ctx, dEnv.DoltDB, h, opts.numLines, matchFunc) + if len(opts.excludingCommitSpecs) == 0 { + commits, err = commitwalk.GetTopNTopoOrderedCommitsMatching(ctx, dEnv.DoltDB, hashes, opts.numLines, matchFunc) } else { - excludingCommit, err := dEnv.DoltDB.Resolve(ctx, opts.excludingCommitSpec, dEnv.RepoStateReader().CWBHeadRef()) - if err != nil { - cli.PrintErrln(color.HiRedString("Fatal error: cannot get excluding commit for current branch.")) - return 1 + excludingHashes := make([]hash.Hash, len(opts.excludingCommitSpecs)) + + for i, excludingSpec := range opts.excludingCommitSpecs { + excludingCommit, err := dEnv.DoltDB.Resolve(ctx, excludingSpec, dEnv.RepoStateReader().CWBHeadRef()) + if err != nil { + cli.PrintErrln(color.HiRedString("Fatal error: cannot get excluding commit for current branch.")) + return 1 + } + + excludingHash, err := excludingCommit.HashOf() + if err != nil { + cli.PrintErrln(color.HiRedString("Fatal error: failed to get commit hash")) + return 1 + } + + excludingHashes[i] = excludingHash } - excludingHash, err := excludingCommit.HashOf() - - if err != nil { - cli.PrintErrln(color.HiRedString("Fatal error: failed to get commit hash")) - return 1 - } - - commits, err = commitwalk.GetDotDotRevisions(ctx, dEnv.DoltDB, h, dEnv.DoltDB, excludingHash, opts.numLines) + commits, err = commitwalk.GetDotDotRevisions(ctx, dEnv.DoltDB, hashes, dEnv.DoltDB, excludingHashes, opts.numLines) } if err != nil { - cli.PrintErrln("Error retrieving commit.") + cli.PrintErrln(err) return 1 } @@ -417,7 +371,7 @@ func logCommits(ctx context.Context, dEnv *env.DoltEnv, opts *logOpts) int { commitHash: cmHash, parentHashes: pHashes, branchNames: cHashToRefs[cmHash], - isHead: cmHash == h}) + isHead: hashIsHead(cmHash, hashes)}) } logToStdOut(opts, commitsInfo) @@ -425,6 +379,13 @@ func logCommits(ctx context.Context, dEnv *env.DoltEnv, opts *logOpts) int { return 0 } +func hashIsHead(cmHash hash.Hash, hashes []hash.Hash) bool { + if len(hashes) > 1 || len(hashes) == 0 { + return false + } + return cmHash == hashes[0] +} + func tableExists(ctx context.Context, commit *doltdb.Commit, tableName string) (bool, error) { rv, err := commit.GetRootValue(ctx) if err != nil { @@ -440,31 +401,37 @@ func tableExists(ctx context.Context, commit *doltdb.Commit, tableName string) ( } func logTableCommits(ctx context.Context, dEnv *env.DoltEnv, opts *logOpts) error { - commit, err := dEnv.DoltDB.Resolve(ctx, opts.commitSpec, dEnv.RepoStateReader().CWBHeadRef()) - if err != nil { - return err - } + hashes := make([]hash.Hash, len(opts.commitSpecs)) - // Check that the table exists in the head commit - exists, err := tableExists(ctx, commit, opts.tableName) - if err != nil { - return err - } + for i, cs := range opts.commitSpecs { + commit, err := dEnv.DoltDB.Resolve(ctx, cs, dEnv.RepoStateReader().CWBHeadRef()) + if err != nil { + return err + } - if !exists { - return fmt.Errorf("error: table %s does not exist", opts.tableName) - } + h, err := commit.HashOf() + if err != nil { + return err + } - h, err := commit.HashOf() - if err != nil { - return err + // Check that the table exists in the head commits + exists, err := tableExists(ctx, commit, opts.tableName) + if err != nil { + return err + } + + if !exists { + return fmt.Errorf("error: table %s does not exist", opts.tableName) + } + + hashes[i] = h } matchFunc := func(commit *doltdb.Commit) (bool, error) { return commit.NumParents() >= opts.minParents, nil } - itr, err := commitwalk.GetTopologicalOrderIterator(ctx, dEnv.DoltDB, h, matchFunc) + itr, err := commitwalk.GetTopologicalOrderIterator(ctx, dEnv.DoltDB, hashes, matchFunc) if err != nil && err != io.EOF { return err } diff --git a/go/cmd/dolt/commands/merge_base.go b/go/cmd/dolt/commands/merge_base.go index 6d4bc628f9..622baf4576 100644 --- a/go/cmd/dolt/commands/merge_base.go +++ b/go/cmd/dolt/commands/merge_base.go @@ -86,6 +86,7 @@ func (cmd MergeBaseCmd) Exec(ctx context.Context, commandStr string, args []stri } cli.Println(mergeBaseStr) + return 0 } diff --git a/go/cmd/dolt/commands/status.go b/go/cmd/dolt/commands/status.go index ffdf03f638..b747bbc5ba 100644 --- a/go/cmd/dolt/commands/status.go +++ b/go/cmd/dolt/commands/status.go @@ -219,7 +219,7 @@ func printRemoteRefTrackingInfo(ctx context.Context, dEnv *env.DoltEnv) error { // countCommitsInRange returns the number of commits between the given starting point to trace back to the given target point. // The starting commit must be a descendant of the target commit. Target commit must be a common ancestor commit. func countCommitsInRange(ctx context.Context, ddb *doltdb.DoltDB, startCommitHash, targetCommitHash hash.Hash) (int, error) { - itr, iErr := commitwalk.GetTopologicalOrderIterator(ctx, ddb, startCommitHash, nil) + itr, iErr := commitwalk.GetTopologicalOrderIterator(ctx, ddb, []hash.Hash{startCommitHash}, nil) if iErr != nil { return 0, iErr } diff --git a/go/libraries/doltcore/env/actions/commitwalk/commitwalk.go b/go/libraries/doltcore/env/actions/commitwalk/commitwalk.go index 1daa9abda2..8db050cb18 100644 --- a/go/libraries/doltcore/env/actions/commitwalk/commitwalk.go +++ b/go/libraries/doltcore/env/actions/commitwalk/commitwalk.go @@ -158,71 +158,54 @@ func newQueue() *q { // ties are broken by timestamp; newer commits appear first. // // Roughly mimics `git log main..feature`. -func GetDotDotRevisions(ctx context.Context, includedDB *doltdb.DoltDB, includedHead hash.Hash, excludedDB *doltdb.DoltDB, excludedHead hash.Hash, num int) ([]*doltdb.Commit, error) { +func GetDotDotRevisions(ctx context.Context, includedDB *doltdb.DoltDB, includedHeads []hash.Hash, excludedDB *doltdb.DoltDB, excludedHeads []hash.Hash, num int) ([]*doltdb.Commit, error) { + itr, err := GetDotDotRevisionsIterator(ctx, includedDB, includedHeads, excludedDB, excludedHeads, nil) + if err != nil { + return nil, err + } + var commitList []*doltdb.Commit - q := newQueue() - if err := q.SetInvisible(ctx, excludedDB, excludedHead); err != nil { - return nil, err - } - if err := q.AddPendingIfUnseen(ctx, excludedDB, excludedHead); err != nil { - return nil, err - } - if err := q.AddPendingIfUnseen(ctx, includedDB, includedHead); err != nil { - return nil, err - } - for q.NumVisiblePending() > 0 { - nextC := q.PopPending() - parents, err := nextC.commit.ParentHashes(ctx) - if err != nil { + for num < 0 || len(commitList) < num { + _, commit, err := itr.Next(ctx) + if err == io.EOF { + break + } else if err != nil { return nil, err } - for _, parentID := range parents { - if nextC.invisible { - if err := q.SetInvisible(ctx, nextC.ddb, parentID); err != nil { - return nil, err - } - } - if err := q.AddPendingIfUnseen(ctx, nextC.ddb, parentID); err != nil { - return nil, err - } - } - if !nextC.invisible { - commitList = append(commitList, nextC.commit) - if len(commitList) == num { - return commitList, nil - } - } + + commitList = append(commitList, commit) } + return commitList, nil } -// GetTopologicalOrderCommits returns the commits reachable from the commit at hash `startCommitHash` +// GetTopologicalOrderCommits returns the commits reachable from the commits in `startCommitHashes` // in reverse topological order, with tiebreaking done by the height of the commit graph -- higher commits // appear first. Remaining ties are broken by timestamp; newer commits appear first. -func GetTopologicalOrderCommits(ctx context.Context, ddb *doltdb.DoltDB, startCommitHash hash.Hash) ([]*doltdb.Commit, error) { - return GetTopNTopoOrderedCommitsMatching(ctx, ddb, startCommitHash, -1, nil) +func GetTopologicalOrderCommits(ctx context.Context, ddb *doltdb.DoltDB, startCommitHashes []hash.Hash) ([]*doltdb.Commit, error) { + return GetTopNTopoOrderedCommitsMatching(ctx, ddb, startCommitHashes, -1, nil) } // GetTopologicalOrderCommitIterator returns an iterator for commits generated with the same semantics as // GetTopologicalOrderCommits -func GetTopologicalOrderIterator(ctx context.Context, ddb *doltdb.DoltDB, startCommitHash hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (doltdb.CommitItr, error) { - return newCommiterator(ctx, ddb, startCommitHash, matchFn) +func GetTopologicalOrderIterator(ctx context.Context, ddb *doltdb.DoltDB, startCommitHashes []hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (doltdb.CommitItr, error) { + return newCommiterator(ctx, ddb, startCommitHashes, matchFn) } type commiterator struct { - ddb *doltdb.DoltDB - startCommitHash hash.Hash - matchFn func(*doltdb.Commit) (bool, error) - q *q + ddb *doltdb.DoltDB + startCommitHashes []hash.Hash + matchFn func(*doltdb.Commit) (bool, error) + q *q } var _ doltdb.CommitItr = (*commiterator)(nil) -func newCommiterator(ctx context.Context, ddb *doltdb.DoltDB, startCommitHash hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (*commiterator, error) { +func newCommiterator(ctx context.Context, ddb *doltdb.DoltDB, startCommitHashes []hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (*commiterator, error) { itr := &commiterator{ - ddb: ddb, - startCommitHash: startCommitHash, - matchFn: matchFn, + ddb: ddb, + startCommitHashes: startCommitHashes, + matchFn: matchFn, } err := itr.Reset(ctx) @@ -270,17 +253,19 @@ func (i *commiterator) Next(ctx context.Context) (hash.Hash, *doltdb.Commit, err // Reset implements doltdb.CommitItr func (i *commiterator) Reset(ctx context.Context) error { i.q = newQueue() - if err := i.q.AddPendingIfUnseen(ctx, i.ddb, i.startCommitHash); err != nil { - return err + for _, startCommitHash := range i.startCommitHashes { + if err := i.q.AddPendingIfUnseen(ctx, i.ddb, startCommitHash); err != nil { + return err + } } return nil } -// GetTopNTopoOrderedCommitsMatching returns the first N commits (If N <= 0 then all commits) reachable from the commit at hash -// `startCommitHash` in reverse topological order, with tiebreaking done by the height of the commit graph -- higher +// GetTopNTopoOrderedCommitsMatching returns the first N commits (If N <= 0 then all commits) reachable from the commits in +// `startCommitHashes` in reverse topological order, with tiebreaking done by the height of the commit graph -- higher // commits appear first. Remaining ties are broken by timestamp; newer commits appear first. -func GetTopNTopoOrderedCommitsMatching(ctx context.Context, ddb *doltdb.DoltDB, startCommitHash hash.Hash, n int, matchFn func(*doltdb.Commit) (bool, error)) ([]*doltdb.Commit, error) { - itr, err := GetTopologicalOrderIterator(ctx, ddb, startCommitHash, matchFn) +func GetTopNTopoOrderedCommitsMatching(ctx context.Context, ddb *doltdb.DoltDB, startCommitHashes []hash.Hash, n int, matchFn func(*doltdb.Commit) (bool, error)) ([]*doltdb.Commit, error) { + itr, err := GetTopologicalOrderIterator(ctx, ddb, startCommitHashes, matchFn) if err != nil { return nil, err } @@ -302,26 +287,28 @@ func GetTopNTopoOrderedCommitsMatching(ctx context.Context, ddb *doltdb.DoltDB, // GetDotDotRevisionsIterator returns an iterator for commits generated with the same semantics as // GetDotDotRevisions -func GetDotDotRevisionsIterator(ctx context.Context, ddb *doltdb.DoltDB, startCommitHash, excludingCommitHash hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (doltdb.CommitItr, error) { - return newDotDotCommiterator(ctx, ddb, startCommitHash, excludingCommitHash, matchFn) +func GetDotDotRevisionsIterator(ctx context.Context, includedDdb *doltdb.DoltDB, startCommitHashes []hash.Hash, excludedDdb *doltdb.DoltDB, excludingCommitHashes []hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (doltdb.CommitItr, error) { + return newDotDotCommiterator(ctx, includedDdb, startCommitHashes, excludedDdb, excludingCommitHashes, matchFn) } type dotDotCommiterator struct { - ddb *doltdb.DoltDB - startCommitHash hash.Hash - excludingCommitHash hash.Hash - matchFn func(*doltdb.Commit) (bool, error) - q *q + includedDdb *doltdb.DoltDB + excludedDdb *doltdb.DoltDB + startCommitHashes []hash.Hash + excludingCommitHashes []hash.Hash + matchFn func(*doltdb.Commit) (bool, error) + q *q } var _ doltdb.CommitItr = (*dotDotCommiterator)(nil) -func newDotDotCommiterator(ctx context.Context, ddb *doltdb.DoltDB, startCommitHash, excludingCommitHash hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (*dotDotCommiterator, error) { +func newDotDotCommiterator(ctx context.Context, includedDdb *doltdb.DoltDB, startCommitHashes []hash.Hash, excludedDdb *doltdb.DoltDB, excludingCommitHashes []hash.Hash, matchFn func(*doltdb.Commit) (bool, error)) (*dotDotCommiterator, error) { itr := &dotDotCommiterator{ - ddb: ddb, - startCommitHash: startCommitHash, - excludingCommitHash: excludingCommitHash, - matchFn: matchFn, + includedDdb: includedDdb, + excludedDdb: excludedDdb, + startCommitHashes: startCommitHashes, + excludingCommitHashes: excludingCommitHashes, + matchFn: matchFn, } err := itr.Reset(ctx) @@ -373,14 +360,18 @@ func (i *dotDotCommiterator) Next(ctx context.Context) (hash.Hash, *doltdb.Commi // Reset implements doltdb.CommitItr func (i *dotDotCommiterator) Reset(ctx context.Context) error { i.q = newQueue() - if err := i.q.SetInvisible(ctx, i.ddb, i.excludingCommitHash); err != nil { - return err + for _, excludingCommitHash := range i.excludingCommitHashes { + if err := i.q.SetInvisible(ctx, i.excludedDdb, excludingCommitHash); err != nil { + return err + } + if err := i.q.AddPendingIfUnseen(ctx, i.excludedDdb, excludingCommitHash); err != nil { + return err + } } - if err := i.q.AddPendingIfUnseen(ctx, i.ddb, i.excludingCommitHash); err != nil { - return err - } - if err := i.q.AddPendingIfUnseen(ctx, i.ddb, i.startCommitHash); err != nil { - return err + for _, startCommitHash := range i.startCommitHashes { + if err := i.q.AddPendingIfUnseen(ctx, i.includedDdb, startCommitHash); err != nil { + return err + } } return nil } diff --git a/go/libraries/doltcore/env/actions/commitwalk/commitwalk_test.go b/go/libraries/doltcore/env/actions/commitwalk/commitwalk_test.go index a3a96dfd8d..1539edf9ef 100644 --- a/go/libraries/doltcore/env/actions/commitwalk/commitwalk_test.go +++ b/go/libraries/doltcore/env/actions/commitwalk/commitwalk_test.go @@ -121,7 +121,7 @@ func TestGetDotDotRevisions(t *testing.T) { mainHash := mustGetHash(t, mainCommits[6]) featurePreMergeHash := mustGetHash(t, featureCommits[3]) - res, err := GetDotDotRevisions(context.Background(), dEnv.DoltDB, featureHash, dEnv.DoltDB, mainHash, 100) + res, err := GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{featureHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 100) require.NoError(t, err) assert.Len(t, res, 7) @@ -133,25 +133,25 @@ func TestGetDotDotRevisions(t *testing.T) { assertEqualHashes(t, featureCommits[2], res[5]) assertEqualHashes(t, featureCommits[1], res[6]) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, mainHash, dEnv.DoltDB, featureHash, 100) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{mainHash}, dEnv.DoltDB, []hash.Hash{featureHash}, 100) require.NoError(t, err) assert.Len(t, res, 0) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, featureHash, dEnv.DoltDB, mainHash, 3) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{featureHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 3) require.NoError(t, err) assert.Len(t, res, 3) assertEqualHashes(t, featureCommits[7], res[0]) assertEqualHashes(t, featureCommits[6], res[1]) assertEqualHashes(t, featureCommits[5], res[2]) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, featurePreMergeHash, dEnv.DoltDB, mainHash, 3) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{featurePreMergeHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 3) require.NoError(t, err) assert.Len(t, res, 3) assertEqualHashes(t, featureCommits[3], res[0]) assertEqualHashes(t, featureCommits[2], res[1]) assertEqualHashes(t, featureCommits[1], res[2]) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, featurePreMergeHash, dEnv.DoltDB, mainHash, 3) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{featurePreMergeHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 3) require.NoError(t, err) assert.Len(t, res, 3) assertEqualHashes(t, featureCommits[3], res[0]) @@ -170,9 +170,9 @@ func TestGetDotDotRevisions(t *testing.T) { mainHash = mustGetHash(t, mainCommits[6]) featurePreMergeHash = mustGetHash(t, featureCommits[3]) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, featureHash, dEnv.DoltDB, mainHash, 100) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{featureHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 100) require.Error(t, err) - res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, featureHash, dEnv.DoltDB, mainHash, 100) + res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, []hash.Hash{featureHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 100) require.NoError(t, err) assert.Len(t, res, 7) assertEqualHashes(t, featureCommits[7], res[0]) @@ -183,27 +183,27 @@ func TestGetDotDotRevisions(t *testing.T) { assertEqualHashes(t, featureCommits[2], res[5]) assertEqualHashes(t, featureCommits[1], res[6]) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, mainHash, dEnv.DoltDB, featureHash, 100) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{mainHash}, dEnv.DoltDB, []hash.Hash{featureHash}, 100) require.Error(t, err) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, mainHash, forkEnv.DoltDB, featureHash, 100) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{mainHash}, forkEnv.DoltDB, []hash.Hash{featureHash}, 100) require.NoError(t, err) assert.Len(t, res, 0) - res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, featureHash, dEnv.DoltDB, mainHash, 3) + res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, []hash.Hash{featureHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 3) require.NoError(t, err) assert.Len(t, res, 3) assertEqualHashes(t, featureCommits[7], res[0]) assertEqualHashes(t, featureCommits[6], res[1]) assertEqualHashes(t, featureCommits[5], res[2]) - res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, featurePreMergeHash, dEnv.DoltDB, mainHash, 3) + res, err = GetDotDotRevisions(context.Background(), dEnv.DoltDB, []hash.Hash{featurePreMergeHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 3) require.NoError(t, err) assert.Len(t, res, 3) assertEqualHashes(t, featureCommits[3], res[0]) assertEqualHashes(t, featureCommits[2], res[1]) assertEqualHashes(t, featureCommits[1], res[2]) - res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, featurePreMergeHash, dEnv.DoltDB, mainHash, 3) + res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, []hash.Hash{featurePreMergeHash}, dEnv.DoltDB, []hash.Hash{mainHash}, 3) require.NoError(t, err) assert.Len(t, res, 3) assertEqualHashes(t, featureCommits[3], res[0]) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index fe825f42ad..6aaa30df67 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -37,6 +37,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/sqle/globalstate" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil" "github.com/dolthub/dolt/go/libraries/doltcore/table/editor" + "github.com/dolthub/dolt/go/store/hash" ) var ErrInvalidTableName = errors.NewKind("Invalid table name %s. Table names must match the regular expression " + doltdb.TableNameRegexStr) @@ -511,12 +512,12 @@ func resolveAsOfTime(ctx *sql.Context, ddb *doltdb.DoltDB, head ref.DoltRef, asO return nil, nil, err } - hash, err := cm.HashOf() + h, err := cm.HashOf() if err != nil { return nil, nil, err } - cmItr, err := commitwalk.GetTopologicalOrderIterator(ctx, ddb, hash, nil) + cmItr, err := commitwalk.GetTopologicalOrderIterator(ctx, ddb, []hash.Hash{h}, nil) if err != nil { return nil, nil, err } diff --git a/go/libraries/doltcore/sqle/dolt_log_table_function.go b/go/libraries/doltcore/sqle/dolt_log_table_function.go index b0bf57dacd..7e6ed6bd0f 100644 --- a/go/libraries/doltcore/sqle/dolt_log_table_function.go +++ b/go/libraries/doltcore/sqle/dolt_log_table_function.go @@ -547,12 +547,12 @@ type logTableFunctionRowIter struct { } func (ltf *LogTableFunction) NewLogTableFunctionRowIter(ctx *sql.Context, ddb *doltdb.DoltDB, commit *doltdb.Commit, matchFn func(*doltdb.Commit) (bool, error), cHashToRefs map[hash.Hash][]string) (*logTableFunctionRowIter, error) { - hash, err := commit.HashOf() + h, err := commit.HashOf() if err != nil { return nil, err } - child, err := commitwalk.GetTopologicalOrderIterator(ctx, ddb, hash, matchFn) + child, err := commitwalk.GetTopologicalOrderIterator(ctx, ddb, []hash.Hash{h}, matchFn) if err != nil { return nil, err } @@ -562,12 +562,12 @@ func (ltf *LogTableFunction) NewLogTableFunctionRowIter(ctx *sql.Context, ddb *d showParents: ltf.showParents, decoration: ltf.decoration, cHashToRefs: cHashToRefs, - headHash: hash, + headHash: h, }, nil } func (ltf *LogTableFunction) NewDotDotLogTableFunctionRowIter(ctx *sql.Context, ddb *doltdb.DoltDB, commit, excludingCommit *doltdb.Commit, matchFn func(*doltdb.Commit) (bool, error), cHashToRefs map[hash.Hash][]string) (*logTableFunctionRowIter, error) { - hash, err := commit.HashOf() + h, err := commit.HashOf() if err != nil { return nil, err } @@ -577,7 +577,7 @@ func (ltf *LogTableFunction) NewDotDotLogTableFunctionRowIter(ctx *sql.Context, return nil, err } - child, err := commitwalk.GetDotDotRevisionsIterator(ctx, ddb, hash, exHash, matchFn) + child, err := commitwalk.GetDotDotRevisionsIterator(ctx, ddb, []hash.Hash{h}, ddb, []hash.Hash{exHash}, matchFn) if err != nil { return nil, err } @@ -587,7 +587,7 @@ func (ltf *LogTableFunction) NewDotDotLogTableFunctionRowIter(ctx *sql.Context, showParents: ltf.showParents, decoration: ltf.decoration, cHashToRefs: cHashToRefs, - headHash: hash, + headHash: h, }, nil } diff --git a/go/libraries/doltcore/sqle/dtables/log_table.go b/go/libraries/doltcore/sqle/dtables/log_table.go index cb1418e194..d4aab1c506 100644 --- a/go/libraries/doltcore/sqle/dtables/log_table.go +++ b/go/libraries/doltcore/sqle/dtables/log_table.go @@ -18,6 +18,7 @@ import ( "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/dolt/go/libraries/doltcore/env/actions/commitwalk" + "github.com/dolthub/dolt/go/store/hash" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/index" @@ -81,12 +82,12 @@ type LogItr struct { // NewLogItr creates a LogItr from the current environment. func NewLogItr(ctx *sql.Context, ddb *doltdb.DoltDB, head *doltdb.Commit) (*LogItr, error) { - hash, err := head.HashOf() + h, err := head.HashOf() if err != nil { return nil, err } - child, err := commitwalk.GetTopologicalOrderIterator(ctx, ddb, hash, nil) + child, err := commitwalk.GetTopologicalOrderIterator(ctx, ddb, []hash.Hash{h}, nil) if err != nil { return nil, err } diff --git a/go/store/datas/commit.go b/go/store/datas/commit.go index 61f5f04d35..417e017040 100644 --- a/go/store/datas/commit.go +++ b/go/store/datas/commit.go @@ -363,7 +363,7 @@ func findCommonAncestorUsingParentsList(ctx context.Context, c1, c2 *Commit, vr1 // FindCommonAncestor returns the most recent common ancestor of c1 and c2, if // one exists, setting ok to true. If there is no common ancestor, ok is set // to false. Refs of |c1| are dereferenced through |vr1|, while refs of |c2| -// are dereference through |vr2|. +// are dereferenced through |vr2|. // // This implementation makes use of the parents_closure field on the commit // struct. If the commit does not have a materialized parents_closure, this diff --git a/integration-tests/bats/log.bats b/integration-tests/bats/log.bats index 64b6295a1c..211a0dfcec 100755 --- a/integration-tests/bats/log.bats +++ b/integration-tests/bats/log.bats @@ -105,6 +105,13 @@ teardown() { [[ ! "$output" =~ "MAIN" ]] || false [[ ! "$output" =~ "AFTER" ]] || false [[ "$output" =~ "BRANCH1" ]] || false + run dolt log ^main ^branch1 + [ $status -eq 0 ] + run dolt log main branch1 + [ $status -eq 0 ] + [[ "$output" =~ "MAIN" ]] || false + [[ "$output" =~ "AFTER" ]] || false + [[ "$output" =~ "BRANCH1" ]] || false # Invalid two dot run dolt log main..branch1 testtable @@ -119,12 +126,10 @@ teardown() { [ $status -eq 1 ] run dolt log main main..branch1 [ $status -eq 1 ] - run dolt log ^main ^branch1 - [ $status -eq 1 ] - run dolt log main branch1 - [ $status -eq 1 ] run dolt log ^main testtable [ $status -eq 1 ] + run dolt log testtable ^main + [ $status -eq 1 ] run dolt log ^branch1 --not main [ $status -eq 1 ] run dolt log main..branch1 --not main diff --git a/integration-tests/bats/merge-base.bats b/integration-tests/bats/merge-base.bats index 92d3d1cf7e..f9b18c5b15 100644 --- a/integration-tests/bats/merge-base.bats +++ b/integration-tests/bats/merge-base.bats @@ -27,7 +27,7 @@ setup() { # / # # / <-- (one) # # / / # - # (init) -- (A) -- (B) -- (C) <-- (main) # + # (init) -- (A) -- (B) -- (C) <-- (main) # # \ # # -- (D) <-- (two) # # #