diff --git a/cmd/git-sync/main.go b/cmd/git-sync/main.go index e581c301a..23e8dadc2 100644 --- a/cmd/git-sync/main.go +++ b/cmd/git-sync/main.go @@ -673,6 +673,18 @@ func setRepoReady() { repoReady = true } +// cleanupWorkTree() is used to remove a worktree and its folder +func cleanupWorkTree(ctx context.Context, gitRoot, worktree string) error { + // Clean up worktree(s) + log.V(1).Info("removing worktree", "path", worktree) + if err := os.RemoveAll(worktree); err != nil { + return fmt.Errorf("error removing directory: %v", err) + } else if _, err := runCommand(ctx, gitRoot, *flGitCmd, "worktree", "prune"); err != nil { + return err + } + return nil +} + // addWorktreeAndSwap creates a new worktree and calls updateSymlink to swap the symlink to point to the new worktree func addWorktreeAndSwap(ctx context.Context, gitRoot, dest, branch, rev string, depth int, hash string, submoduleMode string) error { log.V(0).Info("syncing git", "rev", rev, "hash", hash) @@ -695,6 +707,17 @@ func addWorktreeAndSwap(ctx context.Context, gitRoot, dest, branch, rev string, // Make a worktree for this exact git hash. worktreePath := filepath.Join(gitRoot, hash) + + // Avoid wedge cases where the worktree was created but this function error'd without cleaning the worktree. + // Next timearound, the sync loop fails to create the worktree and bails out. + // Error observed: + // " Run(git worktree add /repo/root/rev-nnnn origin/develop): + // exit status 128: { stdout: \"Preparing worktree (detached HEAD nnnn)\\n\", stderr: \"fatal: '/repo/root/rev-nnnn' already exists\\n\" }" + //. " + if err := cleanupWorkTree(ctx, gitRoot, worktreePath); err != nil { + return err + } + _, err := runCommand(ctx, gitRoot, *flGitCmd, "worktree", "add", worktreePath, "origin/"+branch, "--no-checkout") log.V(0).Info("adding worktree", "path", worktreePath, "branch", fmt.Sprintf("origin/%s", branch)) if err != nil { @@ -808,12 +831,7 @@ func addWorktreeAndSwap(ctx context.Context, gitRoot, dest, branch, rev string, // Clean up previous worktree(s). var cleanupErr error if oldWorktree != "" { - log.V(1).Info("removing old worktree", "path", oldWorktree) - if err := os.RemoveAll(oldWorktree); err != nil { - cleanupErr = fmt.Errorf("error removing directory: %v", err) - } else if _, err := runCommand(ctx, gitRoot, *flGitCmd, "worktree", "prune"); err != nil { - cleanupErr = err - } + cleanupErr = cleanupWorkTree(ctx, gitRoot, oldWorktree) } if cleanupErr != nil { diff --git a/test_e2e.sh b/test_e2e.sh index af953b6b3..32b0e0f1d 100755 --- a/test_e2e.sh +++ b/test_e2e.sh @@ -310,6 +310,41 @@ assert_file_eq "$ROOT"/link/file "$TESTCASE 1" # Wrap up pass +############################################## +# Test worktree-cleanup +############################################## +testcase "worktree-cleanup" + +echo "$TESTCASE" > "$REPO"/file +git -C "$REPO" commit -qam "$TESTCASE" +GIT_SYNC \ + --wait=10 \ + --repo="file://$REPO" \ + --branch=e2e-branch \ + --rev=HEAD \ + --root="$ROOT" \ + --dest="link" \ + > "$DIR"/log."$TESTCASE" 2>&1 & + +# wait for first sync +sleep 4 +assert_link_exists "$ROOT"/link +assert_file_exists "$ROOT"/link/file +assert_file_eq "$ROOT"/link/file "$TESTCASE" + +# second commit +echo "$TESTCASE-ok" > "$REPO"/file2 +git -C "$REPO" add file2 +git -C "$REPO" commit -qam "$TESTCASE new file" +REV=$(git -C "$REPO" rev-list -n1 HEAD) +git -C "$REPO" worktree add -q "$ROOT"/"$REV" -b e2e --no-checkout +sleep 10 + +assert_file_exists "$ROOT"/link/file2 +assert_file_eq "$ROOT"/link/file2 "$TESTCASE-ok" +# Wrap up +pass + ############################################## # Test readlink ##############################################