mirror of
https://git.proxmox.com/git/libgit2
synced 2025-10-14 17:34:40 +00:00
Merge remote-tracking branch 'nulltoken/topic/branch-rework' into development
This commit is contained in:
commit
b41a30bdbb
@ -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.
|
||||
* Move/rename an existing local branch reference.
|
||||
*
|
||||
* @param repo Repository where lives the branch.
|
||||
*
|
||||
* @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
|
||||
|
@ -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.
|
||||
* Check if a reference is a local branch.
|
||||
*
|
||||
* The input reference has to be located in the `refs/heads`
|
||||
* namespace.
|
||||
* @param ref A git reference
|
||||
*
|
||||
* @param tracking_ref Pointer where to store the retrieved
|
||||
* reference.
|
||||
*
|
||||
* @param branch_ref A git local branch 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
|
||||
|
125
src/branch.c
125
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)
|
||||
{
|
||||
git_reference *reference = NULL;
|
||||
git_buf old_reference_name = GIT_BUF_INIT, new_reference_name = GIT_BUF_INIT;
|
||||
int error = 0;
|
||||
giterr_set(GITERR_INVALID, "Reference '%s' is not a local branch.", git_reference_name(ref));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((error = git_buf_joinpath(&old_reference_name, GIT_REFS_HEADS_DIR, old_branch_name)) < 0)
|
||||
goto cleanup;
|
||||
int git_branch_move(
|
||||
git_reference *branch,
|
||||
const char *new_branch_name,
|
||||
int force)
|
||||
{
|
||||
git_buf new_reference_name = GIT_BUF_INIT;
|
||||
int error;
|
||||
|
||||
/* 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;
|
||||
assert(branch && new_branch_name);
|
||||
|
||||
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;
|
||||
}
|
||||
|
17
src/branch.h
17
src/branch.h
@ -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
|
73
src/refs.c
73
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(ref);
|
||||
|
||||
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));
|
||||
|
||||
cleanup:
|
||||
git_config_free(config);
|
||||
git_buf_free(&buf);
|
||||
return error;
|
||||
return git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) == 0;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "refs.h"
|
||||
#include "branch.h"
|
||||
|
||||
static git_repository *repo;
|
||||
static git_reference *fake_remote;
|
||||
|
@ -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 {
|
||||
|
35
tests-clar/refs/branches/lookup.c
Normal file
35
tests-clar/refs/branches/lookup.c
Normal file
@ -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));
|
||||
}
|
@ -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;
|
||||
|
||||
cl_git_pass(git_reference_lookup(&tag, repo, "refs/tags/e90810b"));
|
||||
cl_git_fail(git_branch_move(tag, NEW_BRANCH_NAME, 0));
|
||||
|
||||
git_reference_free(tag);
|
||||
}
|
||||
|
||||
void test_refs_branches_move__can_force_move_over_an_existing_branch(void)
|
||||
{
|
||||
cl_git_pass(git_branch_move(repo, "br2", "master", 1));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void test_refs_branches_move__moving_a_non_exisiting_branch_returns_ENOTFOUND(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));
|
||||
}
|
||||
|
69
tests-clar/refs/branches/tracking.c
Normal file
69
tests-clar/refs/branches/tracking.c
Normal file
@ -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);
|
||||
}
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -15,3 +15,6 @@
|
||||
[branch "master"]
|
||||
remote = test
|
||||
merge = refs/heads/master
|
||||
[branch "track-local"]
|
||||
remote = .
|
||||
merge = refs/heads/master
|
||||
|
1
tests-clar/resources/testrepo.git/refs/heads/track-local
Normal file
1
tests-clar/resources/testrepo.git/refs/heads/track-local
Normal file
@ -0,0 +1 @@
|
||||
9fd738e8f7967c078dceed8190330fc8648ee56a
|
Loading…
Reference in New Issue
Block a user