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

Fix checkout methods that use notifyBlock/GTCheckoutStrategySafe #510

Merged
merged 6 commits into from
Aug 27, 2015

Conversation

dleehr
Copy link
Contributor

@dleehr dleehr commented Aug 19, 2015

Previously, performCheckout method moved HEAD to the target, then called git_checkout_head(). This does not match behavior in git core, and prevents the checkoutStrategy and notifyCallback parameters from being used correctly. The only way to reliably checkout a branch or commit was to use GTCheckoutStrategyForce, which throws away conflicts. Also, the HEAD could be moved even if the checkout fails, resulting in a confused state.

This PR corrects the checkout behavior with two changes:

  1. HEAD is not moved until after the checkout succeeds.
  2. git_checkout_tree() is used instead of git_checkout_head(). The tree that is checked out is the target object (commit or ref).

Included tests demonstrate the correct behavior catching a conflicted file. The notifyBlock is called to report the conflict, and with GTCheckoutStrategySafe, the checkout fails because of the conflict as expected.

Currently, the performCheckout methods move HEAD to the new ref/commit before calling git_checkout_head. This is incorrect behavior.

When git_checkout_head is called, it reports changes between the workdir and HEAD per-file to the notifyBlock, allowing the block to abort the checkout based on a reason (dirty/conflict/etc).

However, since HEAD has already been moved to a different ref/commit, the notifyBlock is notified about changes between the current workdir and the requested ref/commit. This results in a dirty state for any file that differs between the old ref and the new ref, regardless of whether or not any change was made in the workdir.

The correct behavior (e.g. with GTCheckoutStrategySafe) is to notify of changes that will cause data loss in the workdir.

This change leaves HEAD in position until after the checkout, correcting the checkout behavior. When GTCheckoutStrategySafe is used, notifyBlock is only invoked as expected (e.g. dirty files that would be overwritten on checkout). Also, HEAD is only moved if the checkout succeeds, preventing other confusing behavior.
@phatblat phatblat self-assigned this Aug 25, 2015
@phatblat
Copy link
Member

Nice work! 👾

phatblat added a commit that referenced this pull request Aug 27, 2015
Fix checkout methods that use notifyBlock/GTCheckoutStrategySafe
@phatblat phatblat merged commit 9560b9f into libgit2:master Aug 27, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants