Merge pull request #7929 from dolthub/macneale4/fetch-empty

dolt fetch default spec from empty repo should return silently
This commit is contained in:
Neil Macneale IV
2024-05-30 14:35:53 -07:00
committed by GitHub
6 changed files with 49 additions and 10 deletions

View File

@@ -320,7 +320,7 @@ func shallowCloneDataPull(ctx context.Context, destData env.DbData, srcDB *doltd
return nil, fmt.Errorf("remote %s not found", remoteName)
}
specs, err := env.ParseRefSpecs([]string{branch}, destData.Rsr, remote)
specs, _, err := env.ParseRefSpecs([]string{branch}, destData.Rsr, remote)
if err != nil {
return nil, err
}

View File

@@ -476,7 +476,7 @@ func ShallowFetchRefSpec(
return fmt.Errorf("invalid depth: %d", depth)
}
return fetchRefSpecsWithDepth(ctx, dbData, srcDB, []ref.RemoteRefSpec{refSpecs}, remote, ref.ForceUpdate, depth, nil, nil)
return fetchRefSpecsWithDepth(ctx, dbData, srcDB, []ref.RemoteRefSpec{refSpecs}, false, remote, ref.ForceUpdate, depth, nil, nil)
}
// FetchRefSpecs is the common SQL and CLI entrypoint for fetching branches, tags, and heads from a remote.
@@ -487,19 +487,34 @@ func FetchRefSpecs(
dbData env.DbData,
srcDB *doltdb.DoltDB,
refSpecs []ref.RemoteRefSpec,
defaultRefSpec bool,
remote *env.Remote,
mode ref.UpdateMode,
progStarter ProgStarter,
progStopper ProgStopper,
) error {
return fetchRefSpecsWithDepth(ctx, dbData, srcDB, refSpecs, remote, mode, -1, progStarter, progStopper)
return fetchRefSpecsWithDepth(ctx, dbData, srcDB, refSpecs, defaultRefSpec, remote, mode, -1, progStarter, progStopper)
}
// fetchRefSpecsWithDepth fetches the remote refSpecs from the source database to the destination database. It fetches
// the commits and all underlying data from the source database to the destination database.
// Parameters:
// - ctx: the context
// - dbData: the env.DbData object for handling repoState read and write
// - srcDB: the remote *doltdb.DoltDB object that is used to fetch remote branches from
// - refSpecs: the list of refSpecs to fetch
// - defaultRefSpecs: a boolean that indicates whether the refSpecs are the default refSpecs. False if the user specifies anything.
// - remote: the remote object
// - mode: the ref.UpdateMode object that specifies the update mode (force or not, prune or not)
// - depth: the depth of the fetch. If depth is greater than 0, it is a shallow clone.
// - progStarter: function that starts the progress reporting
// - progStopper: function that stops the progress reporting
func fetchRefSpecsWithDepth(
ctx context.Context,
dbData env.DbData,
srcDB *doltdb.DoltDB,
refSpecs []ref.RemoteRefSpec,
defaultRefSpecs bool,
remote *env.Remote,
mode ref.UpdateMode,
depth int,
@@ -515,6 +530,14 @@ func fetchRefSpecsWithDepth(
return fmt.Errorf("%w: %s", env.ErrFailedToReadDb, err.Error())
}
if len(branchRefs) == 0 {
if defaultRefSpecs {
// The remote has no branches. Nothing to do. Git exits silently, so we do too.
return nil
}
return fmt.Errorf("no branches found in remote '%s'", remote.Name)
}
// We build up two structures:
// 1) The list of chunk addresses to fetch, representing the remote branch heads.
// 2) A mapping from branch HEAD to the remote tracking ref we're going to update.

View File

@@ -416,12 +416,15 @@ func RemoteForFetchArgs(args []string, rsr RepoStateReader) (Remote, []string, e
}
// ParseRefSpecs returns the ref specs for the string arguments given for the remote provided, or the default ref
// specs for that remote if no arguments are provided.
func ParseRefSpecs(args []string, rsr RepoStateReader, remote Remote) ([]ref.RemoteRefSpec, error) {
// specs for that remote if no arguments are provided. In the event that the default ref specs are returned, the
// returned boolean value will be true.
func ParseRefSpecs(args []string, rsr RepoStateReader, remote Remote) ([]ref.RemoteRefSpec, bool, error) {
if len(args) != 0 {
return ParseRSFromArgs(remote.Name, args)
specs, err := ParseRSFromArgs(remote.Name, args)
return specs, false, err
} else {
return GetRefSpecs(rsr, remote.Name)
specs, err := GetRefSpecs(rsr, remote.Name)
return specs, true, err
}
}

View File

@@ -69,7 +69,7 @@ func doDoltFetch(ctx *sql.Context, args []string) (int, error) {
return cmdFailure, validationErr
}
refSpecs, err := env.ParseRefSpecs(refSpecArgs, dbData.Rsr, remote)
refSpecs, defaultRefSpec, err := env.ParseRefSpecs(refSpecArgs, dbData.Rsr, remote)
if err != nil {
return cmdFailure, err
}
@@ -87,7 +87,7 @@ func doDoltFetch(ctx *sql.Context, args []string) (int, error) {
prune := apr.Contains(cli.PruneFlag)
mode := ref.UpdateMode{Force: true, Prune: prune}
err = actions.FetchRefSpecs(ctx, dbData, srcDB, refSpecs, &remote, mode, runProgFuncs, stopProgFuncs)
err = actions.FetchRefSpecs(ctx, dbData, srcDB, refSpecs, defaultRefSpec, &remote, mode, runProgFuncs, stopProgFuncs)
if err != nil {
return cmdFailure, fmt.Errorf("fetch failed: %w", err)
}

View File

@@ -152,7 +152,7 @@ func doDoltPull(ctx *sql.Context, args []string) (int, int, string, error) {
}
mode := ref.UpdateMode{Force: true, Prune: false}
err = actions.FetchRefSpecs(ctx, dbData, srcDB, pullSpec.RefSpecs, &pullSpec.Remote, mode, runProgFuncs, stopProgFuncs)
err = actions.FetchRefSpecs(ctx, dbData, srcDB, pullSpec.RefSpecs, false, &pullSpec.Remote, mode, runProgFuncs, stopProgFuncs)
if err != nil {
return noConflictsOrViolations, threeWayMerge, "", fmt.Errorf("fetch failed: %w", err)
}

View File

@@ -391,6 +391,19 @@ teardown() {
[[ "$output" =~ "invalid fetch spec: ''" ]] || false
}
@test "fetch: fetching from empty remote" {
cd repo2
dolt remote add empty file://../empty
setup_remote_server
dolt fetch empty
run dolt fetch empty main
[ "$status" -eq 1 ]
[[ "$output" =~ "no branches found in remote 'empty'" ]] || false
}
@test "fetch: fetch from remote host fails" {
run dolt --host hostedHost --port 3306 --user root --password password fetch origin
[ "$status" -eq 1 ]