Skip to content

git_reference_rename eagerly delete references #4301

Open

Description

@tiennou

While investigating the reflog issue, I noticed git_reference_rename might be too eager in deleting the old ref. Here's a test case demonstrating it :

void test_wip_wip__renaming_borked_new_ref_doesnt_delete_old(void)
{
	git_reference *head_ref, *current_ref, *renamed_ref;
	int err;
	git_oid oid;
	git_reference *victim_ref;
	git_buf victim_path = GIT_BUF_INIT;
	struct stat victim_stat;
	__uint32_t victim_flags;

	cl_git_pass(git_repository_head(&head_ref, g_repo));
	cl_git_pass(git_reference_resolve(&current_ref, head_ref));

	cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/master"));
	cl_git_pass(git_reference_create(&victim_ref, g_repo, VICTIM_REFNAME, &oid, 1, NULL));

	git_buf_joinpath(&victim_path, git_repository_path(g_repo), git_reference_name(victim_ref));

	cl_must_pass(p_stat(git_buf_cstr(&victim_path), &victim_stat));
	victim_flags = victim_stat.st_flags;

	cl_must_pass(chflags(git_buf_cstr(&victim_path), victim_flags|UF_IMMUTABLE));

	err = git_reference_rename(&renamed_ref, current_ref, git_reference_name(victim_ref), 1, NULL);

	cl_must_pass(chflags(git_buf_cstr(&victim_path), victim_flags));
	git_buf_free(&victim_path);

	cl_git_fail_with(GIT_ERROR, err);

	cl_git_pass(git_reference_resolve(&current_ref, head_ref));

	git_reference_free(victim_ref);
}

Thus the original branch is lost, and the repository ends up in a state where its HEAD branch points to a non-existing branch.

Activity

  1. tiennou commented on Jul 8, 2017

    @tiennou
    ContributorAuthor

    I can try to come up with a fix, but ultimately I need something that looks like what git_transaction does, and I don't think the layering allows that... @carlosmn ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions