mirror of
https://github.com/dolthub/dolt.git
synced 2026-03-01 10:09:41 -06:00
Allow multiple refs for dolt log
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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 <ref/^ref/revision-range/table>
|
||||
case 1:
|
||||
return getCommitOrTableFromString(ctx, apr.Arg(0), dEnv, true)
|
||||
|
||||
// dolt log <ref/^ref> <ref/^ref/table>
|
||||
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 <ref> <table>
|
||||
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 <ref> <table>)
|
||||
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 <ref> <ref>
|
||||
}
|
||||
if firstExNotCs != nil && secondExNotCs != nil {
|
||||
return nil, nil, "", fmt.Errorf("Cannot exclude two commit refs") // dolt log ^<ref> ^<ref>
|
||||
}
|
||||
// dolt log ^<ref> <ref>
|
||||
if firstExNotCs != nil && secondCs != nil {
|
||||
return secondCs, firstExNotCs, "", nil
|
||||
}
|
||||
// dolt log <ref> ^<ref>
|
||||
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) {
|
||||
// <ref>...<ref>
|
||||
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
|
||||
}
|
||||
|
||||
// <ref>..<ref>
|
||||
if strings.Contains(str, "..") {
|
||||
if !canDot {
|
||||
return nil, nil, "", fmt.Errorf("Cannot use two dot when 2 arguments provided")
|
||||
// `dolt log <ref>..<ref>`
|
||||
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
|
||||
}
|
||||
|
||||
// ^<ref>
|
||||
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 {
|
||||
// ^<ref>
|
||||
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())
|
||||
// <ref>
|
||||
if argIsRef && !seenRefs[arg] {
|
||||
cs, err := getCommitSpec(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
seenRefs[arg] = true
|
||||
opts.commitSpecs = append(opts.commitSpecs, cs)
|
||||
} else {
|
||||
// <table>
|
||||
opts.tableName = arg
|
||||
}
|
||||
}
|
||||
return nil, notCs, "", err
|
||||
}
|
||||
|
||||
argIsRef := actions.ValidateIsRef(ctx, str, dEnv.DoltDB, dEnv.RepoStateReader())
|
||||
// <ref>
|
||||
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")
|
||||
}
|
||||
|
||||
// <table>
|
||||
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
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ func (cmd MergeBaseCmd) Exec(ctx context.Context, commandStr string, args []stri
|
||||
}
|
||||
|
||||
cli.Println(mergeBaseStr)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -27,7 +27,7 @@ setup() {
|
||||
# / #
|
||||
# / <-- (one) #
|
||||
# / / #
|
||||
# (init) -- (A) -- (B) -- (C) <-- (main) #
|
||||
# (init) -- (A) -- (B) -- (C) <-- (main) #
|
||||
# \ #
|
||||
# -- (D) <-- (two) #
|
||||
# #
|
||||
|
||||
Reference in New Issue
Block a user