Support shallow sync when the rev is not in-range
If I ask for `--depth 1` and a branch, it's fine. If I ask for `--depth 1` and a tag, and that tag is not within 1 commit of the branch that was cloned, it will give an error. Oddly, if the initial `clone` was OK, and subsequent syncs drift, it is OK, because of how we `fetch`. But if it is too far away at the beginning, kaboom. This betrays that the current model of `--branch` and `--rev` is really broken, and should be revamped. For now, I did something simple - if the rev can't be found, try a fetch. A "real" fix is more involved. Also add tests.
This commit is contained in:
parent
12a1d1e298
commit
ff0a73f5ad
|
|
@ -1345,7 +1345,7 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
|
|||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
hash, err = git.LocalHashForRev(ctx, git.rev)
|
||||
hash, err = git.ensureLocalHashForRev(ctx, git.rev)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
|
|
@ -1368,6 +1368,46 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
|
|||
return true, hash, git.AddWorktreeAndSwap(ctx, hash)
|
||||
}
|
||||
|
||||
func (git *repoSync) ensureLocalHashForRev(ctx context.Context, rev string) (string, error) {
|
||||
hash, err := git.LocalHashForRev(ctx, rev)
|
||||
if err == nil {
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
// git might return either error, based on flags used internal to
|
||||
// LocalHashForRev, so we will consider either one to be a "rev not found".
|
||||
if es := err.Error(); !stringContainsOneOf(es, "unknown revision", "bad revision") {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// The rev was not found, try to fetch it.
|
||||
git.log.V(1).Info("rev was not found, trying fetch", "rev", git.rev)
|
||||
args := []string{"fetch", "-f", "--tags"}
|
||||
if git.depth != 0 {
|
||||
args = append(args, "--depth", strconv.Itoa(git.depth))
|
||||
}
|
||||
args = append(args, git.repo, "--")
|
||||
if _, err := git.run.Run(ctx, git.root, nil, git.cmd, args...); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Try again.
|
||||
hash, err = git.LocalHashForRev(ctx, git.rev)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
func stringContainsOneOf(s string, matches ...string) bool {
|
||||
for _, m := range matches {
|
||||
if strings.Contains(s, m) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetRevs returns the local and upstream hashes for rev.
|
||||
func (git *repoSync) GetRevs(ctx context.Context) (string, string, error) {
|
||||
// Ask git what the exact hash is for rev.
|
||||
|
|
|
|||
53
test_e2e.sh
53
test_e2e.sh
|
|
@ -934,10 +934,10 @@ function e2e::sync_slow_git_long_timeout() {
|
|||
##############################################
|
||||
# Test depth syncing
|
||||
##############################################
|
||||
function e2e::sync_depth_shallow() {
|
||||
function e2e::sync_branch_depth_shallow() {
|
||||
# First sync
|
||||
echo "$FUNCNAME 1" > "$REPO"/file
|
||||
expected_depth="1"
|
||||
echo "$FUNCNAME 1" > "$REPO"/file
|
||||
git -C "$REPO" commit -qam "$FUNCNAME 1"
|
||||
|
||||
GIT_SYNC \
|
||||
|
|
@ -981,6 +981,55 @@ function e2e::sync_depth_shallow() {
|
|||
fi
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Test depth syncing with a tag not within depth
|
||||
##############################################
|
||||
function e2e::sync_tag_depth_shallow_out_of_range() {
|
||||
TAG="e2e-tag"
|
||||
expected_depth="1"
|
||||
|
||||
# First commits, tag is not within --depth
|
||||
echo "$FUNCNAME 1" > "$REPO"/file
|
||||
git -C "$REPO" commit -qam "$FUNCNAME 1"
|
||||
git -C "$REPO" tag -af "$TAG" -m "$FUNCNAME 1" >/dev/null
|
||||
echo "$FUNCNAME 2" > "$REPO"/file
|
||||
git -C "$REPO" commit -qam "$FUNCNAME 2"
|
||||
|
||||
GIT_SYNC \
|
||||
--period=100ms \
|
||||
--repo="file://$REPO" \
|
||||
--branch="$MAIN_BRANCH" \
|
||||
--rev="$TAG" \
|
||||
--depth="$expected_depth" \
|
||||
--root="$ROOT" \
|
||||
--link="link" \
|
||||
>> "$1" 2>&1 &
|
||||
sleep 3
|
||||
assert_link_exists "$ROOT"/link
|
||||
assert_file_exists "$ROOT"/link/file
|
||||
assert_file_eq "$ROOT"/link/file "$FUNCNAME 1"
|
||||
depth=$(GIT_DIR="$ROOT"/link/.git git log | grep commit | wc -l)
|
||||
if [[ $expected_depth != $depth ]]; then
|
||||
fail "initial depth mismatch expected=$expected_depth actual=$depth"
|
||||
fi
|
||||
|
||||
# Make 2 new commits, and tag the older one, so it's not within --depth
|
||||
echo "$FUNCNAME 3" > "$REPO"/file
|
||||
git -C "$REPO" commit -qam "$FUNCNAME 3"
|
||||
SHA=$(git -C "$REPO" rev-parse HEAD)
|
||||
echo "$FUNCNAME 4" > "$REPO"/file
|
||||
git -C "$REPO" commit -qam "$FUNCNAME 4"
|
||||
git -C "$REPO" tag -af "$TAG" -m "$FUNCNAME 3" "$SHA" >/dev/null
|
||||
sleep 3
|
||||
assert_link_exists "$ROOT"/link
|
||||
assert_file_exists "$ROOT"/link/file
|
||||
assert_file_eq "$ROOT"/link/file "$FUNCNAME 3"
|
||||
depth=$(GIT_DIR="$ROOT"/link/.git git log | grep commit | wc -l)
|
||||
if [[ $expected_depth != $depth ]]; then
|
||||
fail "forward depth mismatch expected=$expected_depth actual=$depth"
|
||||
fi
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Test fetch skipping commit
|
||||
##############################################
|
||||
|
|
|
|||
Loading…
Reference in New Issue