From df7525e3e0c76bba009d8ae549fdb5cee9992502 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Sat, 14 Oct 2023 13:52:11 -0700 Subject: [PATCH 1/2] Recover if wrong worktree HEAD --- main.go | 11 ++++++++++ test_e2e.sh | 63 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/main.go b/main.go index 8d5ee3014..20ce00c42 100644 --- a/main.go +++ b/main.go @@ -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 { diff --git a/test_e2e.sh b/test_e2e.sh index 01039f054..36bbee0eb 100755 --- a/test_e2e.sh +++ b/test_e2e.sh @@ -609,7 +609,7 @@ function e2e::worktree_cleanup() { } ############################################## -# Test worktree-unexpected-removal +# Test worktree unexpected removal ############################################## function e2e::worktree_unexpected_removal() { GIT_SYNC \ @@ -635,7 +635,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}}" \ @@ -1294,9 +1339,6 @@ 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" \ @@ -1304,7 +1346,7 @@ 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" # Corrupt it rm -f "$ROOT/link" @@ -1317,7 +1359,7 @@ 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" } ############################################## @@ -1325,9 +1367,6 @@ function e2e::sync_crash_no_link_cleanup_retry() { ############################################## 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" \ @@ -1335,7 +1374,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" # Corrupt it rm -rf "$ROOT/.worktrees/" @@ -1348,7 +1387,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" } ############################################## From 613978afa7371fb5892f94a8d758ee652ee04b5f Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Sat, 14 Oct 2023 15:36:45 -0700 Subject: [PATCH 2/2] e2e: use global 'user.email' config --- test_e2e.sh | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/test_e2e.sh b/test_e2e.sh index 36bbee0eb..a7d657fdd 100755 --- a/test_e2e.sh +++ b/test_e2e.sh @@ -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" @@ -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" @@ -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 \ @@ -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 \ @@ -2473,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" @@ -2484,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" @@ -2581,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" @@ -2662,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" @@ -2693,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" @@ -2704,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" @@ -2741,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" @@ -2778,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" @@ -2799,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" @@ -2858,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" @@ -2877,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" @@ -3399,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