Commit c1b5e8c4 by nulltoken

branch: Make git_branch_remote_name() cope with orphaned heads

parent 0309e850
...@@ -221,7 +221,7 @@ GIT_EXTERN(int) git_branch_is_head( ...@@ -221,7 +221,7 @@ GIT_EXTERN(int) git_branch_is_head(
* *
* @param repo The repository where the branch lives. * @param repo The repository where the branch lives.
* *
* @param branch The reference to the remote tracking branch. * @param canonical_branch_name name of the remote tracking branch.
* *
* @return Number of characters in the reference name * @return Number of characters in the reference name
* including the trailing NUL byte; GIT_ENOTFOUND * including the trailing NUL byte; GIT_ENOTFOUND
...@@ -233,7 +233,7 @@ GIT_EXTERN(int) git_branch_remote_name( ...@@ -233,7 +233,7 @@ GIT_EXTERN(int) git_branch_remote_name(
char *remote_name_out, char *remote_name_out,
size_t buffer_size, size_t buffer_size,
git_repository *repo, git_repository *repo,
git_reference *branch); const char *canonical_branch_name);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -323,7 +323,7 @@ int git_branch_remote_name( ...@@ -323,7 +323,7 @@ int git_branch_remote_name(
char *remote_name_out, char *remote_name_out,
size_t buffer_size, size_t buffer_size,
git_repository *repo, git_repository *repo,
git_reference *branch) const char *canonical_branch_name)
{ {
git_strarray remote_list = {0}; git_strarray remote_list = {0};
size_t i, remote_name_size; size_t i, remote_name_size;
...@@ -332,15 +332,15 @@ int git_branch_remote_name( ...@@ -332,15 +332,15 @@ int git_branch_remote_name(
int error = 0; int error = 0;
char *remote_name = NULL; char *remote_name = NULL;
assert(branch); assert(repo && canonical_branch_name);
if (remote_name_out && buffer_size) if (remote_name_out && buffer_size)
*remote_name_out = '\0'; *remote_name_out = '\0';
/* Verify that this is a remote branch */ /* Verify that this is a remote branch */
if (!git_reference_is_remote(branch)) { if (!git_reference__is_remote(canonical_branch_name)) {
giterr_set(GITERR_INVALID, giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.",
"Reference '%s' is not a remote branch.", branch->name); canonical_branch_name);
error = GIT_ERROR; error = GIT_ERROR;
goto cleanup; goto cleanup;
} }
...@@ -358,7 +358,7 @@ int git_branch_remote_name( ...@@ -358,7 +358,7 @@ int git_branch_remote_name(
/* Defensivly check that we have a fetchspec */ /* Defensivly check that we have a fetchspec */
if (fetchspec && if (fetchspec &&
git_refspec_dst_matches(fetchspec, branch->name)) { git_refspec_dst_matches(fetchspec, canonical_branch_name)) {
/* If we have not already set out yet, then set /* If we have not already set out yet, then set
* it to the matching remote name. Otherwise * it to the matching remote name. Otherwise
* multiple remotes match this reference, and it * multiple remotes match this reference, and it
......
...@@ -1926,10 +1926,15 @@ int git_reference_is_branch(git_reference *ref) ...@@ -1926,10 +1926,15 @@ int git_reference_is_branch(git_reference *ref)
return git_reference__is_branch(ref->name); return git_reference__is_branch(ref->name);
} }
int git_reference__is_remote(const char *ref_name)
{
return git__prefixcmp(ref_name, GIT_REFS_REMOTES_DIR) == 0;
}
int git_reference_is_remote(git_reference *ref) int git_reference_is_remote(git_reference *ref)
{ {
assert(ref); assert(ref);
return git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) == 0; return git_reference__is_remote(ref->name);
} }
static int peel_error(int error, git_reference *ref, const char* msg) static int peel_error(int error, git_reference *ref, const char* msg)
......
...@@ -70,6 +70,7 @@ int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int f ...@@ -70,6 +70,7 @@ int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int f
int git_reference__is_valid_name(const char *refname, unsigned int flags); int git_reference__is_valid_name(const char *refname, unsigned int flags);
int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name); int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name);
int git_reference__is_branch(const char *ref_name); int git_reference__is_branch(const char *ref_name);
int git_reference__is_remote(const char *ref_name);
/** /**
* Lookup a reference by name and try to resolve to an OID. * Lookup a reference by name and try to resolve to an OID.
......
...@@ -34,7 +34,9 @@ static void cleanup_repository(void *path) ...@@ -34,7 +34,9 @@ static void cleanup_repository(void *path)
void test_clone_empty__can_clone_an_empty_local_repo_barely(void) void test_clone_empty__can_clone_an_empty_local_repo_barely(void)
{ {
char *local_name = "refs/heads/master"; char *local_name = "refs/heads/master";
char tracking_name[1024]; const char *expected_tracked_branch_name = "refs/remotes/origin/master";
const char *expected_remote_name = "origin";
char buffer[1024];
git_reference *ref; git_reference *ref;
cl_set_cleanup(&cleanup_repository, "./empty"); cl_set_cleanup(&cleanup_repository, "./empty");
...@@ -46,8 +48,20 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void) ...@@ -46,8 +48,20 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void)
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, local_name)); cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, local_name));
/* ...one can still retrieve the name of the remote tracking reference */ /* ...one can still retrieve the name of the remote tracking reference */
cl_assert_equal_i((int)strlen("refs/remotes/origin/master") + 1U, cl_assert_equal_i((int)strlen(expected_tracked_branch_name) + 1,
git_branch_tracking_name(tracking_name, 1024, g_repo_cloned, local_name)); git_branch_tracking_name(buffer, 1024, g_repo_cloned, local_name));
cl_assert_equal_s(expected_tracked_branch_name, buffer);
/* ...and the name of the remote... */
cl_assert_equal_i((int)strlen(expected_remote_name) + 1,
git_branch_remote_name(buffer, 1024, g_repo_cloned, expected_tracked_branch_name));
cl_assert_equal_s(expected_remote_name, buffer);
/* ...even when the remote HEAD is orphaned as well */
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned,
expected_tracked_branch_name));
} }
void test_clone_empty__can_clone_an_empty_local_repo(void) void test_clone_empty__can_clone_an_empty_local_repo(void)
......
...@@ -35,9 +35,9 @@ void test_refs_branches_remote__can_get_remote_for_branch(void) ...@@ -35,9 +35,9 @@ void test_refs_branches_remote__can_get_remote_for_branch(void)
cl_assert_equal_s("test/master", name); cl_assert_equal_s("test/master", name);
cl_assert_equal_i(expectedRemoteNameLength, cl_assert_equal_i(expectedRemoteNameLength,
git_branch_remote_name(NULL, 0, g_repo, ref)); git_branch_remote_name(NULL, 0, g_repo, git_reference_name(ref)));
cl_assert_equal_i(expectedRemoteNameLength, cl_assert_equal_i(expectedRemoteNameLength,
git_branch_remote_name(remotename, expectedRemoteNameLength, g_repo, ref)); git_branch_remote_name(remotename, expectedRemoteNameLength, g_repo, git_reference_name(ref)));
cl_assert_equal_s("test", remotename); cl_assert_equal_s("test", remotename);
git_reference_free(ref); git_reference_free(ref);
...@@ -56,9 +56,9 @@ void test_refs_branches_remote__insufficient_buffer_returns_error(void) ...@@ -56,9 +56,9 @@ void test_refs_branches_remote__insufficient_buffer_returns_error(void)
cl_assert_equal_s("test/master", name); cl_assert_equal_s("test/master", name);
cl_assert_equal_i(expectedRemoteNameLength, cl_assert_equal_i(expectedRemoteNameLength,
git_branch_remote_name(NULL, 0, g_repo, ref)); git_branch_remote_name(NULL, 0, g_repo, git_reference_name(ref)));
cl_git_fail_with(GIT_ERROR, cl_git_fail_with(GIT_ERROR,
git_branch_remote_name(remotename, expectedRemoteNameLength - 1, g_repo, ref)); git_branch_remote_name(remotename, expectedRemoteNameLength - 1, g_repo, git_reference_name(ref)));
git_reference_free(ref); git_reference_free(ref);
} }
...@@ -78,7 +78,7 @@ void test_refs_branches_remote__no_matching_remote_returns_error(void) ...@@ -78,7 +78,7 @@ void test_refs_branches_remote__no_matching_remote_returns_error(void)
cl_git_pass(git_branch_name(&name, ref)); cl_git_pass(git_branch_name(&name, ref));
cl_assert_equal_s("nonexistent/master", name); cl_assert_equal_s("nonexistent/master", name);
cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, ref), GIT_ENOTFOUND); cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, git_reference_name(ref)), GIT_ENOTFOUND);
git_reference_free(ref); git_reference_free(ref);
} }
...@@ -91,7 +91,7 @@ void test_refs_branches_remote__local_remote_returns_error(void) ...@@ -91,7 +91,7 @@ void test_refs_branches_remote__local_remote_returns_error(void)
cl_git_pass(git_branch_name(&name, ref)); cl_git_pass(git_branch_name(&name, ref));
cl_assert_equal_s("master",name); cl_assert_equal_s("master",name);
cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, ref), GIT_ERROR); cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, git_reference_name(ref)), GIT_ERROR);
git_reference_free(ref); git_reference_free(ref);
} }
...@@ -114,6 +114,6 @@ void test_refs_branches_remote__ambiguous_remote_returns_error(void) ...@@ -114,6 +114,6 @@ void test_refs_branches_remote__ambiguous_remote_returns_error(void)
cl_git_pass(git_branch_name(&name, ref)); cl_git_pass(git_branch_name(&name, ref));
cl_assert_equal_s("test/master", name); cl_assert_equal_s("test/master", name);
cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, ref), GIT_EAMBIGUOUS); cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, git_reference_name(ref)), GIT_EAMBIGUOUS);
git_reference_free(ref); git_reference_free(ref);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment