Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recover if wrong worktree HEAD #836

Merged
merged 2 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,17 @@ func (git *repoSync) sanityCheckWorktree(ctx context.Context, worktree worktree)
return false
}

// Make sure it is synced to the right commmit.
stdout, _, err := git.Run(ctx, worktree.Path(), "rev-parse", "HEAD")
if err != nil {
git.log.Error(err, "can't get worktree HEAD", "path", worktree.Path())
return false
}
if stdout != worktree.Hash() {
git.log.V(0).Info("worktree HEAD does not match worktree", "path", worktree.Path(), "head", stdout)
return false
}

// Consistency-check the worktree. Don't use --verbose because it can be
// REALLY verbose.
if _, _, err := git.Run(ctx, worktree.Path(), "fsck", "--no-progress", "--connectivity-only"); err != nil {
Expand Down
90 changes: 53 additions & 37 deletions test_e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,6 @@ function clean_work() {
mkdir -p "$WORK"
}

# config_repo sets required git config, so we don't depend on (shared) global git config.
#
# Args:
# $1: directory of git repo
function config_repo() {
local repo=$1

git -C "$repo" config user.email "git-sync-test@example.com"
git -C "$repo" config user.name "git-sync-test"
}

# REPO and REPO2 are the source repos under test.
REPO="$DIR/repo"
REPO2="${REPO}2"
Expand All @@ -218,7 +207,6 @@ function init_repo() {
rm -rf "$REPO"
mkdir -p "$REPO"
git -C "$REPO" init -q -b "$MAIN_BRANCH"
config_repo "$REPO"
echo "$arg" > "$REPO/file"
git -C "$REPO" add file
git -C "$REPO" commit -aqm "init file"
Expand Down Expand Up @@ -394,7 +382,6 @@ function e2e::init_root_is_under_another_repo() {
mkdir -p "$ROOT/subdir/root"
date > "$ROOT/subdir/root/file" # so it is not empty
git -C "$ROOT/subdir" init -q
config_repo "$ROOT/subdir"

GIT_SYNC \
--one-time \
Expand All @@ -412,7 +399,6 @@ function e2e::init_root_is_under_another_repo() {
function e2e::init_root_fails_sanity() {
# Make an invalid git repo.
git -C "$ROOT" init -q
config_repo "$ROOT"
echo "ref: refs/heads/nonexist" > "$ROOT/.git/HEAD"

GIT_SYNC \
Expand Down Expand Up @@ -609,7 +595,7 @@ function e2e::worktree_cleanup() {
}

##############################################
# Test worktree-unexpected-removal
# Test worktree unexpected removal
##############################################
function e2e::worktree_unexpected_removal() {
GIT_SYNC \
Expand All @@ -635,7 +621,52 @@ function e2e::worktree_unexpected_removal() {

# make a unexpected removal
WT=$(git -C "$REPO" rev-list -n1 HEAD)
rm -r "$ROOT/.worktrees/$WT"
rm -r "$ROOT/.worktrees/$WT"

# resume time
docker ps --filter label="git-sync-e2e=$RUNID" --format="{{.ID}}" \
| while read CTR; do
docker unpause "$CTR" >/dev/null
done

echo "$METRIC_GOOD_SYNC_COUNT"

wait_for_sync "${MAXWAIT}"
assert_link_exists "$ROOT/link"
assert_file_exists "$ROOT/link/file"
assert_file_eq "$ROOT/link/file" "$FUNCNAME"
assert_metric_eq "${METRIC_GOOD_SYNC_COUNT}" 2
assert_metric_eq "${METRIC_FETCH_COUNT}" 2
}

##############################################
# Test syncing when the worktree is wrong hash
##############################################
function e2e::sync_recover_wrong_worktree_hash() {
GIT_SYNC \
--period=100ms \
--repo="file://$REPO" \
--root="$ROOT" \
--link="link" \
&

# wait for first sync
wait_for_sync "${MAXWAIT}"
assert_link_exists "$ROOT/link"
assert_file_exists "$ROOT/link/file"
assert_file_eq "$ROOT/link/file" "$FUNCNAME"
assert_metric_eq "${METRIC_GOOD_SYNC_COUNT}" 1
assert_metric_eq "${METRIC_FETCH_COUNT}" 1

# suspend time so we can fake corruption
docker ps --filter label="git-sync-e2e=$RUNID" --format="{{.ID}}" \
| while read CTR; do
docker pause "$CTR" >/dev/null
done

# Corrupt it
echo "unexpected" > "$ROOT/link/file"
git -C "$ROOT/link" commit -qam "corrupt it"

# resume time
docker ps --filter label="git-sync-e2e=$RUNID" --format="{{.ID}}" \
Expand Down Expand Up @@ -1294,17 +1325,14 @@ function e2e::sync_sha_once_sync_different_sha_unknown() {
##############################################
function e2e::sync_crash_no_link_cleanup_retry() {
# First sync
echo "$FUNCNAME 1" > "$REPO/file"
git -C "$REPO" commit -qam "$FUNCNAME 1"

GIT_SYNC \
--one-time \
--repo="file://$REPO" \
--root="$ROOT" \
--link="link"
assert_link_exists "$ROOT/link"
assert_file_exists "$ROOT/link/file"
assert_file_eq "$ROOT/link/file" "$FUNCNAME 1"
assert_file_eq "$ROOT/link/file" "$FUNCNAME"

# Corrupt it
rm -f "$ROOT/link"
Expand All @@ -1317,25 +1345,22 @@ function e2e::sync_crash_no_link_cleanup_retry() {
--link="link"
assert_link_exists "$ROOT/link"
assert_file_exists "$ROOT/link/file"
assert_file_eq "$ROOT/link/file" "$FUNCNAME 1"
assert_file_eq "$ROOT/link/file" "$FUNCNAME"
}

##############################################
# Test syncing after a crash
##############################################
function e2e::sync_crash_no_worktree_cleanup_retry() {
# First sync
echo "$FUNCNAME 1" > "$REPO/file"
git -C "$REPO" commit -qam "$FUNCNAME 1"

GIT_SYNC \
--one-time \
--repo="file://$REPO" \
--root="$ROOT" \
--link="link"
assert_link_exists "$ROOT/link"
assert_file_exists "$ROOT/link/file"
assert_file_eq "$ROOT/link/file" "$FUNCNAME 1"
assert_file_eq "$ROOT/link/file" "$FUNCNAME"

# Corrupt it
rm -rf "$ROOT/.worktrees/"
Expand All @@ -1348,7 +1373,7 @@ function e2e::sync_crash_no_worktree_cleanup_retry() {
--link="link"
assert_link_exists "$ROOT/link"
assert_file_exists "$ROOT/link/file"
assert_file_eq "$ROOT/link/file" "$FUNCNAME 1"
assert_file_eq "$ROOT/link/file" "$FUNCNAME"
}

##############################################
Expand Down Expand Up @@ -2434,7 +2459,6 @@ function e2e::submodule_sync_default() {
mkdir "$SUBMODULE"

git -C "$SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$SUBMODULE"
echo "submodule" > "$SUBMODULE/submodule.file"
git -C "$SUBMODULE" add submodule.file
git -C "$SUBMODULE" commit -aqm "init submodule.file"
Expand All @@ -2445,7 +2469,6 @@ function e2e::submodule_sync_default() {
mkdir "$NESTED_SUBMODULE"

git -C "$NESTED_SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$NESTED_SUBMODULE"
echo "nested-submodule" > "$NESTED_SUBMODULE/nested-submodule.file"
git -C "$NESTED_SUBMODULE" add nested-submodule.file
git -C "$NESTED_SUBMODULE" commit -aqm "init nested-submodule.file"
Expand Down Expand Up @@ -2542,7 +2565,6 @@ function e2e::submodule_sync_depth() {
mkdir "$SUBMODULE"

git -C "$SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$SUBMODULE"

# First sync
expected_depth="1"
Expand Down Expand Up @@ -2623,7 +2645,6 @@ function e2e::submodule_sync_off() {
mkdir "$SUBMODULE"

git -C "$SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$SUBMODULE"
echo "submodule" > "$SUBMODULE/submodule.file"
git -C "$SUBMODULE" add submodule.file
git -C "$SUBMODULE" commit -aqm "init submodule file"
Expand Down Expand Up @@ -2654,7 +2675,6 @@ function e2e::submodule_sync_shallow() {
mkdir "$SUBMODULE"

git -C "$SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$SUBMODULE"
echo "submodule" > "$SUBMODULE/submodule.file"
git -C "$SUBMODULE" add submodule.file
git -C "$SUBMODULE" commit -aqm "init submodule file"
Expand All @@ -2665,7 +2685,6 @@ function e2e::submodule_sync_shallow() {
mkdir "$NESTED_SUBMODULE"

git -C "$NESTED_SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$NESTED_SUBMODULE"
echo "nested-submodule" > "$NESTED_SUBMODULE/nested-submodule.file"
git -C "$NESTED_SUBMODULE" add nested-submodule.file
git -C "$NESTED_SUBMODULE" commit -aqm "init nested-submodule file"
Expand Down Expand Up @@ -2702,7 +2721,6 @@ function e2e::submodule_sync_relative() {
mkdir "$SUBMODULE"

git -C "$SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$SUBMODULE"
echo "submodule" > "$SUBMODULE/submodule.file"
git -C "$SUBMODULE" add submodule.file
git -C "$SUBMODULE" commit -aqm "init submodule file"
Expand Down Expand Up @@ -2739,7 +2757,6 @@ function e2e::submodule_sync_over_ssh_different_keys() {
mkdir "$NESTED_SUBMODULE"

git -C "$NESTED_SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$NESTED_SUBMODULE"
echo "nested-submodule" > "$NESTED_SUBMODULE/nested-submodule.file"
git -C "$NESTED_SUBMODULE" add nested-submodule.file
git -C "$NESTED_SUBMODULE" commit -aqm "init nested-submodule.file"
Expand All @@ -2760,7 +2777,6 @@ function e2e::submodule_sync_over_ssh_different_keys() {
mkdir "$SUBMODULE"

git -C "$SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$SUBMODULE"
echo "submodule" > "$SUBMODULE/submodule.file"
git -C "$SUBMODULE" add submodule.file
git -C "$SUBMODULE" commit -aqm "init submodule.file"
Expand Down Expand Up @@ -2819,7 +2835,6 @@ function e2e::submodule_sync_over_http_different_passwords() {
mkdir "$NESTED_SUBMODULE"

git -C "$NESTED_SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$NESTED_SUBMODULE"
echo "nested-submodule" > "$NESTED_SUBMODULE/nested-submodule.file"
git -C "$NESTED_SUBMODULE" add nested-submodule.file
git -C "$NESTED_SUBMODULE" commit -aqm "init nested-submodule.file"
Expand All @@ -2838,7 +2853,6 @@ function e2e::submodule_sync_over_http_different_passwords() {
mkdir "$SUBMODULE"

git -C "$SUBMODULE" init -q -b "$MAIN_BRANCH"
config_repo "$SUBMODULE"
echo "submodule" > "$SUBMODULE/submodule.file"
git -C "$SUBMODULE" add submodule.file
git -C "$SUBMODULE" commit -aqm "init submodule.file"
Expand Down Expand Up @@ -3360,6 +3374,8 @@ function run_test() {
# Override local configs for predictability in this test.
export GIT_CONFIG_GLOBAL="$DIR/gitconfig"
export GIT_CONFIG_SYSTEM=/dev/null
git config --global user.email "git-sync-test@example.com"
git config --global user.name "git-sync-test"

# Make sure files we create can be group writable.
umask 0002
Expand Down