diff options
| author | Vicent Marti <tanoku@gmail.com> | 2012-07-27 18:45:55 +0200 | 
|---|---|---|
| committer | Vicent Marti <tanoku@gmail.com> | 2012-07-27 18:45:55 +0200 | 
| commit | b41a30bdbb96dc0eb2d7e30497918ecbb45fd090 (patch) | |
| tree | 00c7d7b1883ac812cde389f771d6371c30615d0e | |
| parent | b84f75c357208ce54c5cc35921ff0b4a1abbe7d2 (diff) | |
| parent | 786a17cd282cf81c76c45a8e62f2a1003235a673 (diff) | |
| download | libgit2-b41a30bdbb96dc0eb2d7e30497918ecbb45fd090.tar.gz | |
Merge remote-tracking branch 'nulltoken/topic/branch-rework' into development
| -rw-r--r-- | include/git2/branch.h | 60 | ||||
| -rw-r--r-- | include/git2/refs.h | 21 | ||||
| -rw-r--r-- | src/branch.c | 125 | ||||
| -rw-r--r-- | src/branch.h | 17 | ||||
| -rw-r--r-- | src/refs.c | 73 | ||||
| -rw-r--r-- | src/revparse.c | 2 | ||||
| -rw-r--r-- | tests-clar/network/remotelocal.c | 4 | ||||
| -rw-r--r-- | tests-clar/refs/branches/create.c | 57 | ||||
| -rw-r--r-- | tests-clar/refs/branches/delete.c | 1 | ||||
| -rw-r--r-- | tests-clar/refs/branches/foreach.c | 5 | ||||
| -rw-r--r-- | tests-clar/refs/branches/lookup.c | 35 | ||||
| -rw-r--r-- | tests-clar/refs/branches/move.c | 50 | ||||
| -rw-r--r-- | tests-clar/refs/branches/tracking.c | 69 | ||||
| -rw-r--r-- | tests-clar/refs/foreachglob.c | 4 | ||||
| -rw-r--r-- | tests-clar/refs/read.c | 16 | ||||
| -rw-r--r-- | tests-clar/refs/remotetracking.c | 49 | ||||
| -rw-r--r-- | tests-clar/resources/testrepo.git/config | 3 | ||||
| -rw-r--r-- | tests-clar/resources/testrepo.git/refs/heads/track-local | 1 | 
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 | 
