diff options
Diffstat (limited to 'save-git.c')
-rw-r--r-- | save-git.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/save-git.c b/save-git.c index 74eab55bb..1488b43bb 100644 --- a/save-git.c +++ b/save-git.c @@ -776,6 +776,38 @@ static git_object *try_to_find_parent(const char *hex_id, git_repository *repo) return (git_object *)commit; } +static int notify_cb(git_checkout_notify_t why, + const char *path, + const git_diff_file *baseline, + const git_diff_file *target, + const git_diff_file *workdir, + void *payload) +{ + report_error("File '%s' does not match in working tree", path); + return 0; /* Continue with checkout */ +} + +static git_tree *get_git_tree(git_repository *repo, git_object *parent) +{ + git_tree *tree; + if (!parent) + return NULL; + if (git_tree_lookup(&tree, repo, git_commit_tree_id((const git_commit *) parent))) + return NULL; + return tree; +} + +static int update_git_checkout(git_repository *repo, git_object *parent, git_tree *tree) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_DIRTY; + opts.notify_cb = notify_cb; + opts.baseline = get_git_tree(repo, parent); + return git_checkout_tree(repo, (git_object *) tree, &opts); +} + /* * libgit2 revision 0.20 and earlier do not have the signature and * message log arguments. @@ -849,6 +881,22 @@ static int create_new_commit(git_repository *repo, const char *branch, git_oid * if (git_branch_create(&ref, repo, branch, commit, 0, author, "Create branch")) return report_error("Failed to create branch '%s'", branch); } + /* + * If it's a checked-out branch, try to also update the working + * tree and index. If that fails (dirty working tree or whatever), + * this is not technically a save error (we did save things in + * the object database), but it can cause extreme confusion, so + * warn about it. + */ + if (git_branch_is_head(ref) && !git_repository_is_bare(repo)) { + if (update_git_checkout(repo, parent, tree)) { + const git_error *err = giterr_last(); + const char *errstr = err ? err->message : strerror(errno); + report_error("Git branch '%s' is checked out, but worktree is dirty (%s)", + branch, errstr); + } + } + if (git_reference_set_target(&ref, ref, &commit_id, author, "Subsurface save event")) return report_error("Failed to update branch '%s'", branch); set_git_id(&commit_id); |