summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2012-07-27 18:45:55 +0200
committerVicent Marti <tanoku@gmail.com>2012-07-27 18:45:55 +0200
commitb41a30bdbb96dc0eb2d7e30497918ecbb45fd090 (patch)
tree00c7d7b1883ac812cde389f771d6371c30615d0e
parentb84f75c357208ce54c5cc35921ff0b4a1abbe7d2 (diff)
parent786a17cd282cf81c76c45a8e62f2a1003235a673 (diff)
downloadlibgit2-b41a30bdbb96dc0eb2d7e30497918ecbb45fd090.tar.gz
Merge remote-tracking branch 'nulltoken/topic/branch-rework' into development
-rw-r--r--include/git2/branch.h60
-rw-r--r--include/git2/refs.h21
-rw-r--r--src/branch.c125
-rw-r--r--src/branch.h17
-rw-r--r--src/refs.c73
-rw-r--r--src/revparse.c2
-rw-r--r--tests-clar/network/remotelocal.c4
-rw-r--r--tests-clar/refs/branches/create.c57
-rw-r--r--tests-clar/refs/branches/delete.c1
-rw-r--r--tests-clar/refs/branches/foreach.c5
-rw-r--r--tests-clar/refs/branches/lookup.c35
-rw-r--r--tests-clar/refs/branches/move.c50
-rw-r--r--tests-clar/refs/branches/tracking.c69
-rw-r--r--tests-clar/refs/foreachglob.c4
-rw-r--r--tests-clar/refs/read.c16
-rw-r--r--tests-clar/refs/remotetracking.c49
-rw-r--r--tests-clar/resources/testrepo.git/config3
-rw-r--r--tests-clar/resources/testrepo.git/refs/heads/track-local1
18 files changed, 325 insertions, 267 deletions
diff --git a/include/git2/branch.h b/include/git2/branch.h
index 8884df15a..15894b709 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -26,9 +26,9 @@ GIT_BEGIN_DECL
* this target commit. If `force` is true and a reference
* already exists with the given name, it'll be replaced.
*
- * @param oid_out Pointer where to store the OID of the target commit.
+ * The returned reference must be freed by the user.
*
- * @param repo Repository where to store the branch.
+ * @param branch_out Pointer where to store the underlying reference.
*
* @param branch_name Name for the branch; this name is
* validated for consistency. It should also not conflict with
@@ -46,8 +46,7 @@ GIT_BEGIN_DECL
* pointing to the provided target commit.
*/
GIT_EXTERN(int) git_branch_create(
- git_oid *oid_out,
- git_repository *repo,
+ git_reference **branch_out,
const char *branch_name,
const git_object *target,
int force);
@@ -97,27 +96,62 @@ GIT_EXTERN(int) git_branch_foreach(
);
/**
- * Move/rename an existing branch reference.
- *
- * @param repo Repository where lives the branch.
+ * Move/rename an existing local branch reference.
*
- * @param old_branch_name Current name of the branch to be moved;
- * this name is validated for consistency.
+ * @param branch Current underlying reference of the branch.
*
* @param new_branch_name Target name of the branch once the move
* is performed; this name is validated for consistency.
*
* @param force Overwrite existing branch.
*
- * @return 0 on success, GIT_ENOTFOUND if the branch
- * doesn't exist or an error code.
+ * @return 0 on success, or an error code.
*/
GIT_EXTERN(int) git_branch_move(
- git_repository *repo,
- const char *old_branch_name,
+ git_reference *branch,
const char *new_branch_name,
int force);
+/**
+ * Lookup a branch by its name in a repository.
+ *
+ * The generated reference must be freed by the user.
+ *
+ * @param branch_out pointer to the looked-up branch reference
+ *
+ * @param repo the repository to look up the branch
+ *
+ * @param branch_name Name of the branch to be looked-up;
+ * this name is validated for consistency.
+ *
+ * @param branch_type Type of the considered branch. This should
+ * be valued with either GIT_BRANCH_LOCAL or GIT_BRANCH_REMOTE.
+ *
+ * @return 0 on success; GIT_ENOTFOUND when no matching branch
+ * exists, otherwise an error code.
+ */
+GIT_EXTERN(int) git_branch_lookup(
+ git_reference **branch_out,
+ git_repository *repo,
+ const char *branch_name,
+ git_branch_t branch_type);
+
+/**
+ * Return the reference supporting the remote tracking branch,
+ * given a local branch reference.
+ *
+ * @param tracking_out Pointer where to store the retrieved
+ * reference.
+ *
+ * @param branch Current underlying reference of the branch.
+ *
+ * @return 0 on success; GIT_ENOTFOUND when no remote tracking
+ * reference exists, otherwise an error code.
+ */
+GIT_EXTERN(int) git_branch_tracking(
+ git_reference **tracking_out,
+ git_reference *branch);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/refs.h b/include/git2/refs.h
index b119e90b1..8dd8e3116 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -363,26 +363,15 @@ GIT_EXTERN(int) git_reference_foreach_glob(
*/
GIT_EXTERN(int) git_reference_has_log(git_reference *ref);
-
/**
- * Return the reference supporting the remote tracking branch,
- * given a reference branch.
- *
- * The input reference has to be located in the `refs/heads`
- * namespace.
- *
- * @param tracking_ref Pointer where to store the retrieved
- * reference.
+ * Check if a reference is a local branch.
*
- * @param branch_ref A git local branch reference.
+ * @param ref A git reference
*
- * @return 0 on success; GIT_ENOTFOUND when no remote tracking
- * reference exists, otherwise an error code.
+ * @return 1 when the reference lives in the refs/heads
+ * namespace; 0 otherwise.
*/
-GIT_EXTERN(int) git_reference_remote_tracking_from_branch(
- git_reference **tracking_ref,
- git_reference *branch_ref
-);
+GIT_EXTERN(int) git_reference_is_branch(git_reference *ref);
/** @} */
GIT_END_DECL
diff --git a/src/branch.c b/src/branch.c
index 671e42051..d11eca8da 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -7,8 +7,11 @@
#include "common.h"
#include "commit.h"
-#include "branch.h"
#include "tag.h"
+#include "config.h"
+#include "refspec.h"
+
+#include "git2/branch.h"
static int retrieve_branch_reference(
git_reference **branch_reference_out,
@@ -48,8 +51,7 @@ static int create_error_invalid(const char *msg)
}
int git_branch_create(
- git_oid *oid_out,
- git_repository *repo,
+ git_reference **ref_out,
const char *branch_name,
const git_object *target,
int force)
@@ -60,10 +62,7 @@ int git_branch_create(
git_buf canonical_branch_name = GIT_BUF_INIT;
int error = -1;
- assert(repo && branch_name && target && oid_out);
-
- if (git_object_owner(target) != repo)
- return create_error_invalid("The given target does not belong to this repository");
+ assert(branch_name && target && ref_out);
target_type = git_object_type(target);
@@ -90,17 +89,17 @@ int git_branch_create(
if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
goto cleanup;
- if (git_reference_create_oid(&branch, repo, git_buf_cstr(&canonical_branch_name), git_object_id(commit), force) < 0)
+ if (git_reference_create_oid(&branch, git_object_owner(commit),
+ git_buf_cstr(&canonical_branch_name), git_object_id(commit), force) < 0)
goto cleanup;
- git_oid_cpy(oid_out, git_reference_oid(branch));
+ *ref_out = branch;
error = 0;
cleanup:
if (target_type == GIT_OBJ_TAG)
git_object_free(commit);
- git_reference_free(branch);
git_buf_free(&canonical_branch_name);
return error;
}
@@ -111,6 +110,7 @@ int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_
git_reference *head = NULL;
int error;
+ assert(repo && branch_name);
assert((branch_type == GIT_BRANCH_LOCAL) || (branch_type == GIT_BRANCH_REMOTE));
if ((error = retrieve_branch_reference(&branch, repo, branch_name, branch_type == GIT_BRANCH_REMOTE)) < 0)
@@ -183,28 +183,109 @@ int git_branch_foreach(
return git_reference_foreach(repo, GIT_REF_LISTALL, &branch_foreach_cb, (void *)&filter);
}
-int git_branch_move(git_repository *repo, const char *old_branch_name, const char *new_branch_name, int force)
+static int not_a_local_branch(git_reference *ref)
+{
+ giterr_set(GITERR_INVALID, "Reference '%s' is not a local branch.", git_reference_name(ref));
+ return -1;
+}
+
+int git_branch_move(
+ git_reference *branch,
+ const char *new_branch_name,
+ int force)
{
- git_reference *reference = NULL;
- git_buf old_reference_name = GIT_BUF_INIT, new_reference_name = GIT_BUF_INIT;
- int error = 0;
+ git_buf new_reference_name = GIT_BUF_INIT;
+ int error;
- if ((error = git_buf_joinpath(&old_reference_name, GIT_REFS_HEADS_DIR, old_branch_name)) < 0)
- goto cleanup;
+ assert(branch && new_branch_name);
- /* We need to be able to return GIT_ENOTFOUND */
- if ((error = git_reference_lookup(&reference, repo, git_buf_cstr(&old_reference_name))) < 0)
- goto cleanup;
+ if (!git_reference_is_branch(branch))
+ return not_a_local_branch(branch);
if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
goto cleanup;
- error = git_reference_rename(reference, git_buf_cstr(&new_reference_name), force);
+ error = git_reference_rename(branch, git_buf_cstr(&new_reference_name), force);
cleanup:
- git_reference_free(reference);
- git_buf_free(&old_reference_name);
git_buf_free(&new_reference_name);
return error;
}
+
+int git_branch_lookup(
+ git_reference **ref_out,
+ git_repository *repo,
+ const char *branch_name,
+ git_branch_t branch_type)
+{
+ assert(ref_out && repo && branch_name);
+
+ return retrieve_branch_reference(ref_out, repo, branch_name, branch_type == GIT_BRANCH_REMOTE);
+}
+
+int retrieve_tracking_configuration(const char **out, git_reference *branch, const char *format)
+{
+ git_config *config;
+ git_buf buf = GIT_BUF_INIT;
+ int error;
+
+ if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0)
+ return -1;
+
+ if (git_buf_printf(&buf, format,
+ git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
+ return -1;
+
+ error = git_config_get_string(out, config, git_buf_cstr(&buf));
+ git_buf_free(&buf);
+ return error;
+}
+
+int git_branch_tracking(
+ git_reference **tracking_out,
+ git_reference *branch)
+{
+ const char *remote_name, *merge_name;
+ git_buf buf = GIT_BUF_INIT;
+ int error = -1;
+ git_remote *remote = NULL;
+ const git_refspec *refspec;
+
+ assert(tracking_out && branch);
+
+ if (!git_reference_is_branch(branch))
+ return not_a_local_branch(branch);
+
+ if ((error = retrieve_tracking_configuration(&remote_name, branch, "branch.%s.remote")) < 0)
+ goto cleanup;
+
+ if ((error = retrieve_tracking_configuration(&merge_name, branch, "branch.%s.merge")) < 0)
+ goto cleanup;
+
+ if (strcmp(".", remote_name) != 0) {
+ if ((error = git_remote_load(&remote, git_reference_owner(branch), remote_name)) < 0)
+ goto cleanup;
+
+ refspec = git_remote_fetchspec(remote);
+ if (refspec == NULL) {
+ error = GIT_ENOTFOUND;
+ goto cleanup;
+ }
+
+ if (git_refspec_transform_r(&buf, refspec, merge_name) < 0)
+ goto cleanup;
+ } else
+ if (git_buf_sets(&buf, merge_name) < 0)
+ goto cleanup;
+
+ error = git_reference_lookup(
+ tracking_out,
+ git_reference_owner(branch),
+ git_buf_cstr(&buf));
+
+cleanup:
+ git_remote_free(remote);
+ git_buf_free(&buf);
+ return error;
+}
diff --git a/src/branch.h b/src/branch.h
deleted file mode 100644
index d0e5abc8b..000000000
--- a/src/branch.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2009-2012 the libgit2 contributors
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_branch_h__
-#define INCLUDE_branch_h__
-
-#include "git2/branch.h"
-
-struct git_branch {
- char *remote; /* TODO: Make this a git_remote */
- char *merge;
-};
-
-#endif
diff --git a/src/refs.c b/src/refs.c
index b3c140bec..32f54fc31 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -11,7 +11,6 @@
#include "fileops.h"
#include "pack.h"
#include "reflog.h"
-#include "config.h"
#include <git2/tag.h>
#include <git2/object.h>
@@ -1816,75 +1815,9 @@ int git_reference_has_log(
return result;
}
-//TODO: How about also taking care of local tracking branches?
-//cf. http://alblue.bandlem.com/2011/07/git-tip-of-week-tracking-branches.html
-int git_reference_remote_tracking_from_branch(
- git_reference **tracking_ref,
- git_reference *branch_ref)
+int git_reference_is_branch(git_reference *ref)
{
- git_config *config = NULL;
- const char *name, *remote, *merge;
- git_buf buf = GIT_BUF_INIT;
- int error = -1;
-
- assert(tracking_ref && branch_ref);
-
- name = git_reference_name(branch_ref);
-
- if (git__prefixcmp(name, GIT_REFS_HEADS_DIR)) {
- giterr_set(
- GITERR_INVALID,
- "Failed to retrieve tracking reference - '%s' is not a branch.",
- name);
- return -1;
- }
-
- if (git_repository_config(&config, branch_ref->owner) < 0)
- return -1;
-
- if (git_buf_printf(
- &buf,
- "branch.%s.remote",
- name + strlen(GIT_REFS_HEADS_DIR)) < 0)
- goto cleanup;
-
- if ((error = git_config_get_string(&remote, config, git_buf_cstr(&buf))) < 0)
- goto cleanup;
-
- error = -1;
-
- git_buf_clear(&buf);
-
- //TODO: Is it ok to fail when no merge target is found?
- if (git_buf_printf(
- &buf,
- "branch.%s.merge",
- name + strlen(GIT_REFS_HEADS_DIR)) < 0)
- goto cleanup;
-
- if (git_config_get_string(&merge, config, git_buf_cstr(&buf)) < 0)
- goto cleanup;
-
- //TODO: Should we test this?
- if (git__prefixcmp(merge, GIT_REFS_HEADS_DIR))
- goto cleanup;
-
- git_buf_clear(&buf);
-
- if (git_buf_printf(
- &buf,
- "refs/remotes/%s/%s",
- remote,
- merge + strlen(GIT_REFS_HEADS_DIR)) < 0)
- goto cleanup;
-
- error = git_reference_lookup(
- tracking_ref,
- branch_ref->owner,
- git_buf_cstr(&buf));
+ assert(ref);
-cleanup:
- git_config_free(config);
- git_buf_free(&buf);
- return error;
+ return git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) == 0;
}
diff --git a/src/revparse.c b/src/revparse.c
index b0469286b..e2c0de612 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -328,7 +328,7 @@ static int retrieve_remote_tracking_reference(git_reference **base_ref, const ch
*base_ref = NULL;
}
- if ((error = git_reference_remote_tracking_from_branch(&tracking, ref)) < 0)
+ if ((error = git_branch_tracking(&tracking, ref)) < 0)
goto cleanup;
*base_ref = tracking;
diff --git a/tests-clar/network/remotelocal.c b/tests-clar/network/remotelocal.c
index 5e20b4240..16e3fe2dd 100644
--- a/tests-clar/network/remotelocal.c
+++ b/tests-clar/network/remotelocal.c
@@ -107,7 +107,7 @@ void test_network_remotelocal__retrieve_advertised_references(void)
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
- cl_assert_equal_i(how_many_refs, 22);
+ cl_assert_equal_i(how_many_refs, 23);
}
void test_network_remotelocal__retrieve_advertised_references_from_spaced_repository(void)
@@ -121,7 +121,7 @@ void test_network_remotelocal__retrieve_advertised_references_from_spaced_reposi
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
- cl_assert_equal_i(how_many_refs, 22);
+ cl_assert_equal_i(how_many_refs, 23);
git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */
remote = NULL;
diff --git a/tests-clar/refs/branches/create.c b/tests-clar/refs/branches/create.c
index ad7e1fd2c..d53904303 100644
--- a/tests-clar/refs/branches/create.c
+++ b/tests-clar/refs/branches/create.c
@@ -1,19 +1,22 @@
#include "clar_libgit2.h"
#include "refs.h"
-#include "branch.h"
static git_repository *repo;
-static git_oid branch_target_oid;
static git_object *target;
+static git_reference *branch;
void test_refs_branches_create__initialize(void)
{
cl_fixture_sandbox("testrepo.git");
cl_git_pass(git_repository_open(&repo, "testrepo.git"));
+
+ branch = NULL;
}
void test_refs_branches_create__cleanup(void)
{
+ git_reference_free(branch);
+
git_object_free(target);
git_repository_free(repo);
@@ -39,54 +42,24 @@ void test_refs_branches_create__can_create_a_local_branch(void)
{
retrieve_known_commit(&target, repo);
- cl_git_pass(git_branch_create(&branch_target_oid, repo, NEW_BRANCH_NAME, target, 0));
- cl_git_pass(git_oid_cmp(&branch_target_oid, git_object_id(target)));
-}
-
-void test_refs_branches_create__creating_a_local_branch_triggers_the_creation_of_a_new_direct_reference(void)
-{
- git_reference *branch;
-
- retrieve_known_commit(&target, repo);
-
- cl_git_fail(git_reference_lookup(&branch, repo, GIT_REFS_HEADS_DIR NEW_BRANCH_NAME));
-
- cl_git_pass(git_branch_create(&branch_target_oid, repo, NEW_BRANCH_NAME, target, 0));
-
- cl_git_pass(git_reference_lookup(&branch, repo, GIT_REFS_HEADS_DIR NEW_BRANCH_NAME));
- cl_assert(git_reference_type(branch) == GIT_REF_OID);
-
- git_reference_free(branch);
+ cl_git_pass(git_branch_create(&branch, NEW_BRANCH_NAME, target, 0));
+ cl_git_pass(git_oid_cmp(git_reference_oid(branch), git_object_id(target)));
}
void test_refs_branches_create__can_not_create_a_branch_if_its_name_collide_with_an_existing_one(void)
{
retrieve_known_commit(&target, repo);
- cl_git_fail(git_branch_create(&branch_target_oid, repo, "br2", target, 0));
+ cl_git_fail(git_branch_create(&branch, "br2", target, 0));
}
void test_refs_branches_create__can_force_create_over_an_existing_branch(void)
{
retrieve_known_commit(&target, repo);
- cl_git_pass(git_branch_create(&branch_target_oid, repo, "br2", target, 1));
- cl_git_pass(git_oid_cmp(&branch_target_oid, git_object_id(target)));
-}
-
-void test_refs_branches_create__can_not_create_a_branch_pointing_at_an_object_unknown_from_the_repository(void)
-{
- git_repository *repo2;
-
- /* Open another instance of the same repository */
- cl_git_pass(git_repository_open(&repo2, cl_fixture("testrepo.git")));
-
- /* Retrieve a commit object from this different repository */
- retrieve_known_commit(&target, repo2);
-
- cl_git_fail(git_branch_create(&branch_target_oid, repo, NEW_BRANCH_NAME, target, 0));
-
- git_repository_free(repo2);
+ cl_git_pass(git_branch_create(&branch, "br2", target, 1));
+ cl_git_pass(git_oid_cmp(git_reference_oid(branch), git_object_id(target)));
+ cl_assert_equal_s("refs/heads/br2", git_reference_name(branch));
}
void test_refs_branches_create__creating_a_branch_targeting_a_tag_dereferences_it_to_its_commit(void)
@@ -94,8 +67,8 @@ void test_refs_branches_create__creating_a_branch_targeting_a_tag_dereferences_i
/* b25fa35 is a tag, pointing to another tag which points to a commit */
retrieve_target_from_oid(&target, repo, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
- cl_git_pass(git_branch_create(&branch_target_oid, repo, NEW_BRANCH_NAME, target, 0));
- cl_git_pass(git_oid_streq(&branch_target_oid, "e90810b8df3e80c413d903f631643c716887138d"));
+ cl_git_pass(git_branch_create(&branch, NEW_BRANCH_NAME, target, 0));
+ cl_git_pass(git_oid_streq(git_reference_oid(branch), "e90810b8df3e80c413d903f631643c716887138d"));
}
void test_refs_branches_create__can_not_create_a_branch_pointing_to_a_non_commit_object(void)
@@ -103,11 +76,11 @@ void test_refs_branches_create__can_not_create_a_branch_pointing_to_a_non_commit
/* 53fc32d is the tree of commit e90810b */
retrieve_target_from_oid(&target, repo, "53fc32d17276939fc79ed05badaef2db09990016");
- cl_git_fail(git_branch_create(&branch_target_oid, repo, NEW_BRANCH_NAME, target, 0));
+ cl_git_fail(git_branch_create(&branch, NEW_BRANCH_NAME, target, 0));
git_object_free(target);
/* 521d87c is an annotated tag pointing to a blob */
retrieve_target_from_oid(&target, repo, "521d87c1ec3aef9824daf6d96cc0ae3710766d91");
- cl_git_fail(git_branch_create(&branch_target_oid, repo, NEW_BRANCH_NAME, target, 0));
+ cl_git_fail(git_branch_create(&branch, NEW_BRANCH_NAME, target, 0));
}
diff --git a/tests-clar/refs/branches/delete.c b/tests-clar/refs/branches/delete.c
index 03d3c56d7..699655f27 100644
--- a/tests-clar/refs/branches/delete.c
+++ b/tests-clar/refs/branches/delete.c
@@ -1,6 +1,5 @@
#include "clar_libgit2.h"
#include "refs.h"
-#include "branch.h"
static git_repository *repo;
static git_reference *fake_remote;
diff --git a/tests-clar/refs/branches/foreach.c b/tests-clar/refs/branches/foreach.c
index b6e973799..794233cc9 100644
--- a/tests-clar/refs/branches/foreach.c
+++ b/tests-clar/refs/branches/foreach.c
@@ -1,6 +1,5 @@
#include "clar_libgit2.h"
#include "refs.h"
-#include "branch.h"
static git_repository *repo;
static git_reference *fake_remote;
@@ -48,7 +47,7 @@ static void assert_retrieval(unsigned int flags, unsigned int expected_count)
void test_refs_branches_foreach__retrieve_all_branches(void)
{
- assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 10);
+ assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 11);
}
void test_refs_branches_foreach__retrieve_remote_branches(void)
@@ -58,7 +57,7 @@ void test_refs_branches_foreach__retrieve_remote_branches(void)
void test_refs_branches_foreach__retrieve_local_branches(void)
{
- assert_retrieval(GIT_BRANCH_LOCAL, 8);
+ assert_retrieval(GIT_BRANCH_LOCAL, 9);
}
struct expectations {
diff --git a/tests-clar/refs/branches/lookup.c b/tests-clar/refs/branches/lookup.c
new file mode 100644
index 000000000..2aabf9889
--- /dev/null
+++ b/tests-clar/refs/branches/lookup.c
@@ -0,0 +1,35 @@
+#include "clar_libgit2.h"
+#include "refs.h"
+
+static git_repository *repo;
+static git_reference *branch;
+
+void test_refs_branches_lookup__initialize(void)
+{
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+ branch = NULL;
+}
+
+void test_refs_branches_lookup__cleanup(void)
+{
+ git_reference_free(branch);
+
+ git_repository_free(repo);
+}
+
+void test_refs_branches_lookup__can_retrieve_a_local_branch(void)
+{
+ cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL));
+}
+
+void test_refs_branches_lookup__can_retrieve_a_remote_tracking_branch(void)
+{
+ cl_git_pass(git_branch_lookup(&branch, repo, "test/master", GIT_BRANCH_REMOTE));
+}
+
+void test_refs_branches_lookup__trying_to_retrieve_an_unknown_branch_returns_ENOTFOUND(void)
+{
+ cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "where/are/you", GIT_BRANCH_LOCAL));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "over/here", GIT_BRANCH_REMOTE));
+}
diff --git a/tests-clar/refs/branches/move.c b/tests-clar/refs/branches/move.c
index 242e5cd01..6750473e1 100644
--- a/tests-clar/refs/branches/move.c
+++ b/tests-clar/refs/branches/move.c
@@ -1,72 +1,64 @@
#include "clar_libgit2.h"
-#include "branch.h"
+#include "refs.h"
static git_repository *repo;
+static git_reference *ref;
void test_refs_branches_move__initialize(void)
{
- cl_fixture_sandbox("testrepo.git");
- cl_git_pass(git_repository_open(&repo, "testrepo.git"));
+ repo = cl_git_sandbox_init("testrepo.git");
+
+ cl_git_pass(git_reference_lookup(&ref, repo, "refs/heads/br2"));
}
void test_refs_branches_move__cleanup(void)
{
- git_repository_free(repo);
-
- cl_fixture_cleanup("testrepo.git");
+ git_reference_free(ref);
+ cl_git_sandbox_cleanup();
}
#define NEW_BRANCH_NAME "new-branch-on-the-block"
void test_refs_branches_move__can_move_a_local_branch(void)
{
- cl_git_pass(git_branch_move(repo, "br2", NEW_BRANCH_NAME, 0));
+ cl_git_pass(git_branch_move(ref, NEW_BRANCH_NAME, 0));
+ cl_assert_equal_s(GIT_REFS_HEADS_DIR NEW_BRANCH_NAME, git_reference_name(ref));
}
void test_refs_branches_move__can_move_a_local_branch_to_a_different_namespace(void)
{
/* Downward */
- cl_git_pass(git_branch_move(repo, "br2", "somewhere/" NEW_BRANCH_NAME, 0));
+ cl_git_pass(git_branch_move(ref, "somewhere/" NEW_BRANCH_NAME, 0));
/* Upward */
- cl_git_pass(git_branch_move(repo, "somewhere/" NEW_BRANCH_NAME, "br2", 0));
+ cl_git_pass(git_branch_move(ref, "br2", 0));
}
void test_refs_branches_move__can_move_a_local_branch_to_a_partially_colliding_namespace(void)
{
/* Downward */
- cl_git_pass(git_branch_move(repo, "br2", "br2/" NEW_BRANCH_NAME, 0));
+ cl_git_pass(git_branch_move(ref, "br2/" NEW_BRANCH_NAME, 0));
/* Upward */
- cl_git_pass(git_branch_move(repo, "br2/" NEW_BRANCH_NAME, "br2", 0));
+ cl_git_pass(git_branch_move(ref, "br2", 0));
}
void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_collide_with_an_existing_one(void)
{
- cl_git_fail(git_branch_move(repo, "br2", "master", 0));
+ cl_git_fail(git_branch_move(ref, "master", 0));
}
-void test_refs_branches_move__can_not_move_a_non_existing_branch(void)
+void test_refs_branches_move__can_not_move_a_non_branch(void)
{
- cl_git_fail(git_branch_move(repo, "i-am-no-branch", NEW_BRANCH_NAME, 0));
-}
+ git_reference *tag;
-void test_refs_branches_move__can_force_move_over_an_existing_branch(void)
-{
- cl_git_pass(git_branch_move(repo, "br2", "master", 1));
-}
+ cl_git_pass(git_reference_lookup(&tag, repo, "refs/tags/e90810b"));
+ cl_git_fail(git_branch_move(tag, NEW_BRANCH_NAME, 0));
-void test_refs_branches_move__can_not_move_a_branch_through_its_canonical_name(void)
-{
- cl_git_fail(git_branch_move(repo, "refs/heads/br2", NEW_BRANCH_NAME, 1));
+ git_reference_free(tag);
}
-void test_refs_branches_move__moving_a_non_exisiting_branch_returns_ENOTFOUND(void)
+void test_refs_branches_move__can_force_move_over_an_existing_branch(void)
{
- int error;
-
- error = git_branch_move(repo, "where/am/I", NEW_BRANCH_NAME, 0);
- cl_git_fail(error);
-
- cl_assert_equal_i(GIT_ENOTFOUND, error);
+ cl_git_pass(git_branch_move(ref, "master", 1));
}
diff --git a/tests-clar/refs/branches/tracking.c b/tests-clar/refs/branches/tracking.c
new file mode 100644
index 000000000..8f7019437
--- /dev/null
+++ b/tests-clar/refs/branches/tracking.c
@@ -0,0 +1,69 @@
+#include "clar_libgit2.h"
+#include "refs.h"
+
+static git_repository *repo;
+static git_reference *branch;
+
+void test_refs_branches_tracking__initialize(void)
+{
+ cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+ branch = NULL;
+}
+
+void test_refs_branches_tracking__cleanup(void)
+{
+ git_reference_free(branch);
+
+ git_repository_free(repo);
+}
+
+void test_refs_branches_tracking__can_retrieve_the_remote_tracking_reference_of_a_local_branch(void)
+{
+ git_reference *branch, *tracking;
+
+ cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
+
+ cl_git_pass(git_branch_tracking(&tracking, branch));
+
+ cl_assert_equal_s("refs/remotes/test/master", git_reference_name(tracking));
+
+ git_reference_free(branch);
+ git_reference_free(tracking);
+}
+
+void test_refs_branches_tracking__can_retrieve_the_local_tracking_reference_of_a_local_branch(void)
+{
+ git_reference *branch, *tracking;
+
+ cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/track-local"));
+
+ cl_git_pass(git_branch_tracking(&tracking, branch));
+
+ cl_assert_equal_s("refs/heads/master", git_reference_name(tracking));
+
+ git_reference_free(branch);
+ git_reference_free(tracking);
+}
+
+void test_refs_branches_tracking__cannot_retrieve_a_remote_tracking_reference_from_a_non_branch(void)
+{
+ git_reference *branch, *tracking;
+
+ cl_git_pass(git_reference_lookup(&branch, repo, "refs/tags/e90810b"));
+
+ cl_git_fail(git_branch_tracking(&tracking, branch));
+
+ git_reference_free(branch);
+}
+
+void test_refs_branches_tracking__trying_to_retrieve_a_remote_tracking_reference_from_a_plain_local_branch_returns_GIT_ENOTFOUND(void)
+{
+ git_reference *branch, *tracking;
+
+ cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/subtrees"));
+
+ cl_assert_equal_i(GIT_ENOTFOUND, git_branch_tracking(&tracking, branch));
+
+ git_reference_free(branch);
+}
diff --git a/tests-clar/refs/foreachglob.c b/tests-clar/refs/foreachglob.c
index d1412a94b..b024d36d4 100644
--- a/tests-clar/refs/foreachglob.c
+++ b/tests-clar/refs/foreachglob.c
@@ -46,7 +46,7 @@ static void assert_retrieval(const char *glob, unsigned int flags, int expected_
void test_refs_foreachglob__retrieve_all_refs(void)
{
/* 7 heads (including one packed head) + 1 note + 2 remotes + 6 tags */
- assert_retrieval("*", GIT_REF_LISTALL, 17);
+ assert_retrieval("*", GIT_REF_LISTALL, 18);
}
void test_refs_foreachglob__retrieve_remote_branches(void)
@@ -56,7 +56,7 @@ void test_refs_foreachglob__retrieve_remote_branches(void)
void test_refs_foreachglob__retrieve_local_branches(void)
{
- assert_retrieval("refs/heads/*", GIT_REF_LISTALL, 8);
+ assert_retrieval("refs/heads/*", GIT_REF_LISTALL, 9);
}
void test_refs_foreachglob__retrieve_partially_named_references(void)
diff --git a/tests-clar/refs/read.c b/tests-clar/refs/read.c
index ce4eefeba..1948e0a56 100644
--- a/tests-clar/refs/read.c
+++ b/tests-clar/refs/read.c
@@ -202,3 +202,19 @@ void test_refs_read__unfound_return_ENOTFOUND(void)
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/master"));
cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master"));
}
+
+static void assert_is_branch(const char *name, bool expected_branchness)
+{
+ git_reference *reference;
+ cl_git_pass(git_reference_lookup(&reference, g_repo, name));
+ cl_assert_equal_i(expected_branchness, git_reference_is_branch(reference));
+ git_reference_free(reference);
+}
+
+void test_refs_read__can_determine_if_a_reference_is_a_local_branch(void)
+{
+ assert_is_branch("refs/heads/master", true);
+ assert_is_branch("refs/heads/packed", true);
+ assert_is_branch("refs/remotes/test/master", false);
+ assert_is_branch("refs/tags/e90810b", false);
+}
diff --git a/tests-clar/refs/remotetracking.c b/tests-clar/refs/remotetracking.c
deleted file mode 100644
index c4ec588ee..000000000
--- a/tests-clar/refs/remotetracking.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "clar_libgit2.h"
-
-static git_repository *g_repo;
-
-void test_refs_remotetracking__initialize(void)
-{
- cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
-}
-
-void test_refs_remotetracking__cleanup(void)
-{
- git_repository_free(g_repo);
-}
-
-void test_refs_remotetracking__unfound_returns_GIT_ENOTFOUND(void)
-{
- git_reference *branch, *tracking;
-
- cl_git_pass(git_reference_lookup(&branch, g_repo, "refs/heads/subtrees"));
-
- cl_assert_equal_i(GIT_ENOTFOUND, git_reference_remote_tracking_from_branch(&tracking, branch));
-
- git_reference_free(branch);
-}
-
-void test_refs_remotetracking__retrieving_from_a_non_head_fails(void)
-{
- git_reference *branch, *tracking;
-
- cl_git_pass(git_reference_lookup(&branch, g_repo, "refs/tags/e90810b"));
-
- cl_git_fail(git_reference_remote_tracking_from_branch(&tracking, branch));
-
- git_reference_free(branch);
-}
-
-void test_refs_remotetracking__can_retrieve_a_remote_tracking_branch_reference(void)
-{
- git_reference *branch, *tracking;
-
- cl_git_pass(git_reference_lookup(&branch, g_repo, "refs/heads/master"));
-
- cl_git_pass(git_reference_remote_tracking_from_branch(&tracking, branch));
-
- cl_assert_equal_s("refs/remotes/test/master", git_reference_name(tracking));
-
- git_reference_free(branch);
- git_reference_free(tracking);
-}
diff --git a/tests-clar/resources/testrepo.git/config b/tests-clar/resources/testrepo.git/config
index c99d97153..04ab38776 100644
--- a/tests-clar/resources/testrepo.git/config
+++ b/tests-clar/resources/testrepo.git/config
@@ -15,3 +15,6 @@
[branch "master"]
remote = test
merge = refs/heads/master
+[branch "track-local"]
+ remote = .
+ merge = refs/heads/master
diff --git a/tests-clar/resources/testrepo.git/refs/heads/track-local b/tests-clar/resources/testrepo.git/refs/heads/track-local
new file mode 100644
index 000000000..f37febb2c
--- /dev/null
+++ b/tests-clar/resources/testrepo.git/refs/heads/track-local
@@ -0,0 +1 @@
+9fd738e8f7967c078dceed8190330fc8648ee56a