Skip to content

Commit d29bc2d

Browse files
committed
Make two attempts to clean repository after checkout
It's not certain that there is any point in another try after a first unsuccessful cleaning attempt. However, go-git's checkout code also does a hard reset, but still leaves the repository dirty under certain circumstances. Running an identical hard reset procedure again gets the repository to a clean state, so this indicates a possibility that a retry might be successful.
1 parent 34ca703 commit d29bc2d

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

internal/libraries/gitutils/gitutils.go

+29-9
Original file line numberDiff line numberDiff line change
@@ -175,28 +175,48 @@ func CheckoutTag(repository *git.Repository, tag *plumbing.Reference) error {
175175
return err
176176
}
177177

178+
// Ensure the repository is checked out to a clean state.
179+
// Because it might not succeed on the first attempt, a retry is allowed.
180+
for range [2]int{} {
181+
clean, err := cleanRepository(repoTree)
182+
if err != nil {
183+
return err
184+
}
185+
if clean {
186+
return nil
187+
}
188+
}
189+
190+
return fmt.Errorf("failed to get repository to clean state")
191+
}
192+
193+
func cleanRepository(repoTree *git.Worktree) (bool, error) {
178194
// Remove now-empty folders which are left behind after checkout. These would not be removed by the reset action.
179195
// Remove untracked files. These would also be removed by the reset action.
180-
if err = repoTree.Clean(&git.CleanOptions{Dir: true}); err != nil {
181-
return err
196+
if err := repoTree.Clean(&git.CleanOptions{Dir: true}); err != nil {
197+
return false, err
182198
}
183199

184200
// Remove untracked files and reset tracked files to clean state.
185201
// Even though in theory it shouldn't ever be necessary to do a hard reset in this application, under certain
186202
// circumstances, go-git can fail to complete checkout, while not even returning an error. This results in an
187203
// unexpected dirty repository state, which is corrected via a hard reset.
188204
// See: https://github.com/go-git/go-git/issues/99
189-
if err = repoTree.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil {
190-
return err
205+
if err := repoTree.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil {
206+
return false, err
191207
}
192208

209+
// Get status to detect some forms of failed cleaning.
193210
repoStatus, err := repoTree.Status()
194211
if err != nil {
195-
return err
196-
}
197-
if !repoStatus.IsClean() {
198-
return fmt.Errorf("failed to get repository to clean state")
212+
return false, err
199213
}
200214

201-
return nil
215+
// IsClean() detects:
216+
// - Untracked files
217+
// - Modified tracked files
218+
// This does not detect:
219+
// - Empty directories
220+
// - Ignored files
221+
return repoStatus.IsClean(), nil
202222
}

0 commit comments

Comments
 (0)