diff options
| author | Patrick Steinhardt <ps@pks.im> | 2017-04-04 18:55:57 +0200 |
|---|---|---|
| committer | Patrick Steinhardt <ps@pks.im> | 2017-04-05 13:50:38 +0200 |
| commit | 2a485dabc02a556c78df7eafe26aa9ffd83e3227 (patch) | |
| tree | c6d47e2ed3e33ab12f88fb8ec1a8f166799feeac /src | |
| parent | 38fc5ab0a235bdb2c35d0ddb3193840c088662a3 (diff) | |
| download | libgit2-2a485dabc02a556c78df7eafe26aa9ffd83e3227.tar.gz | |
refs: update worktree HEADs when renaming branches
Whenever we rename a branch, we update the repository's symbolic HEAD
reference if it currently points to the branch that is to be renamed.
But with the introduction of worktrees, we also have to iterate over all
HEADs of linked worktrees to adjust them. Do so.
Diffstat (limited to 'src')
| -rw-r--r-- | src/refs.c | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/src/refs.c b/src/refs.c index a53d094fc..31410b75f 100644 --- a/src/refs.c +++ b/src/refs.c @@ -614,20 +614,53 @@ int git_reference_symbolic_set_target( out, ref->db->repo, ref->name, target, 1, ref->target.symbolic, log_message); } +typedef struct { + const char *old_name; + git_refname_t new_name; +} rename_cb_data; + +static int update_wt_heads(git_repository *repo, const char *path, void *payload) +{ + rename_cb_data *data = (rename_cb_data *) payload; + git_reference *head; + char *gitdir = NULL; + int error = 0; + + if (git_reference__read_head(&head, repo, path) < 0 || + git_reference_type(head) != GIT_REF_SYMBOLIC || + git__strcmp(head->target.symbolic, data->old_name) != 0 || + (gitdir = git_path_dirname(path)) == NULL) + goto out; + + /* Update HEAD it was pointing to the reference being renamed */ + if ((error = git_repository_create_head(gitdir, data->new_name)) < 0) { + giterr_set(GITERR_REFERENCE, "failed to update HEAD after renaming reference"); + goto out; + } + +out: + git_reference_free(head); + git__free(gitdir); + + return error; +} + static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force, const git_signature *signature, const char *message) { + git_repository *repo; git_refname_t normalized; bool should_head_be_updated = false; int error = 0; assert(ref && new_name && signature); + repo = git_reference_owner(ref); + if ((error = reference_normalize_for_repo( - normalized, git_reference_owner(ref), new_name, true)) < 0) + normalized, repo, new_name, true)) < 0) return error; - /* Check if we have to update HEAD. */ if ((error = git_branch_is_head(ref)) < 0) return error; @@ -637,14 +670,18 @@ static int reference__rename(git_reference **out, git_reference *ref, const char if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0) return error; - /* Update HEAD it was pointing to the reference being renamed */ - if (should_head_be_updated && - (error = git_repository_set_head(ref->db->repo, normalized)) < 0) { - giterr_set(GITERR_REFERENCE, "failed to update HEAD after renaming reference"); - return error; + /* Update HEAD if it was pointing to the reference being renamed */ + if (should_head_be_updated) { + error = git_repository_set_head(ref->db->repo, normalized); + } else { + rename_cb_data payload; + payload.old_name = ref->name; + memcpy(&payload.new_name, &normalized, sizeof(normalized)); + + error = git_repository_foreach_head(repo, update_wt_heads, &payload); } - return 0; + return error; } |
