Commit f9500b45 by Vicent Marti

Merge pull request #2081 from libgit2/bs/reflog

Reflog completionism
parents 8646b0a0 db092c19
......@@ -43,6 +43,12 @@ GIT_BEGIN_DECL
*
* @param force Overwrite existing branch.
*
* @param signature The identity that will used to populate the reflog entry
*
* @param log_message The one line long message to be appended to the reflog.
* If NULL, the default is "Branch: created"; if you want something more
* useful, provide a message.
*
* @return 0, GIT_EINVALIDSPEC or an error code.
* A proper reference is written in the refs/heads namespace
* pointing to the provided target commit.
......@@ -52,7 +58,9 @@ GIT_EXTERN(int) git_branch_create(
git_repository *repo,
const char *branch_name,
const git_commit *target,
int force);
int force,
const git_signature *signature,
const char *log_message);
/**
* Delete an existing branch reference.
......@@ -115,13 +123,19 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter);
*
* @param force Overwrite existing branch.
*
* @param signature The identity that will used to populate the reflog entry
*
* @param log_message The one line long message to be appended to the reflog
*
* @return 0 on success, GIT_EINVALIDSPEC or an error code.
*/
GIT_EXTERN(int) git_branch_move(
git_reference **out,
git_reference *branch,
const char *new_branch_name,
int force);
int force,
const git_signature *signature,
const char *log_message);
/**
* Lookup a branch by its name in a repository.
......
......@@ -45,6 +45,8 @@ GIT_BEGIN_DECL
* default is "origin".
* - `checkout_branch` gives the name of the branch to checkout. NULL
* means use the remote's HEAD.
* - `signature` is the identity used when updating the reflog. NULL means to
* use the default signature using the config.
*/
typedef struct git_clone_options {
......@@ -57,6 +59,7 @@ typedef struct git_clone_options {
int ignore_cert_errors;
const char *remote_name;
const char* checkout_branch;
git_signature *signature;
} git_clone_options;
#define GIT_CLONE_OPTIONS_VERSION 1
......@@ -96,6 +99,7 @@ GIT_EXTERN(int) git_clone(
* @param co_opts options to use during checkout
* @param branch the branch to checkout after the clone, pass NULL for the
* remote's default branch
* @param signature The identity used when updating the reflog.
* @return 0 on success, any non-zero return value from a callback
* function, or a negative value to indicate an error (use
* `giterr_last` for a detailed error message)
......@@ -104,7 +108,8 @@ GIT_EXTERN(int) git_clone_into(
git_repository *repo,
git_remote *remote,
const git_checkout_opts *co_opts,
const char *branch);
const char *branch,
const git_signature *signature);
/** @} */
GIT_END_DECL
......
......@@ -297,6 +297,8 @@ GIT_EXTERN(int) git_reference_set_target(
* @param ref The reference to rename
* @param new_name The new name for the reference
* @param force Overwrite an existing reference
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
* @return 0 on success, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code
*
*/
......@@ -304,7 +306,9 @@ GIT_EXTERN(int) git_reference_rename(
git_reference **new_ref,
git_reference *ref,
const char *new_name,
int force);
int force,
const git_signature *signature,
const char *log_message);
/**
* Delete an existing reference.
......
......@@ -567,11 +567,15 @@ GIT_EXTERN(int) git_repository_hashfile(
*
* @param repo Repository pointer
* @param refname Canonical name of the reference the HEAD should point at
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head(
git_repository* repo,
const char* refname);
const char* refname,
const git_signature *signature,
const char *log_message);
/**
* Make the repository HEAD directly point to the Commit.
......@@ -587,11 +591,15 @@ GIT_EXTERN(int) git_repository_set_head(
*
* @param repo Repository pointer
* @param commitish Object id of the Commit the HEAD should point to
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head_detached(
git_repository* repo,
const git_oid* commitish);
const git_oid* commitish,
const git_signature *signature,
const char *log_message);
/**
* Detach the HEAD.
......
......@@ -54,24 +54,34 @@ int git_branch_create(
git_repository *repository,
const char *branch_name,
const git_commit *commit,
int force)
int force,
const git_signature *signature,
const char *log_message)
{
git_reference *branch = NULL;
git_buf canonical_branch_name = GIT_BUF_INIT;
int error = 0;
git_buf canonical_branch_name = GIT_BUF_INIT,
log_message_buf = GIT_BUF_INIT;
int error = -1;
assert(branch_name && commit && ref_out);
assert(git_object_owner((const git_object *)commit) == repository);
if (!(error = git_buf_joinpath(
&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name)))
error = git_reference_create(
&branch, repository, git_buf_cstr(&canonical_branch_name),
git_commit_id(commit), force, NULL, NULL);
if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0)
goto cleanup;
*ref_out = branch;
if (git_buf_sets(&log_message_buf, log_message ? log_message : "Branch: created") < 0)
goto cleanup;
error = git_reference_create(&branch, repository,
git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force, signature,
git_buf_cstr(&log_message_buf));
if (!error)
*ref_out = branch;
cleanup:
git_buf_free(&canonical_branch_name);
git_buf_free(&log_message_buf);
return error;
}
......@@ -109,6 +119,9 @@ int git_branch_delete(git_reference *branch)
if (git_reference_delete(branch) < 0)
goto on_error;
if (git_reflog_delete(git_reference_owner(branch), git_reference_name(branch)) < 0)
goto on_error;
error = 0;
on_error:
......@@ -185,11 +198,14 @@ int git_branch_move(
git_reference **out,
git_reference *branch,
const char *new_branch_name,
int force)
int force,
const git_signature *signature,
const char *log_message)
{
git_buf new_reference_name = GIT_BUF_INIT,
old_config_section = GIT_BUF_INIT,
new_config_section = GIT_BUF_INIT;
old_config_section = GIT_BUF_INIT,
new_config_section = GIT_BUF_INIT,
log_message_buf = GIT_BUF_INIT;
int error;
assert(branch && new_branch_name);
......@@ -197,14 +213,23 @@ int git_branch_move(
if (!git_reference_is_branch(branch))
return not_a_local_branch(git_reference_name(branch));
error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name);
if (error < 0)
if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0)
goto done;
if (log_message) {
if ((error = git_buf_sets(&log_message_buf, log_message)) < 0)
goto done;
} else {
if ((error = git_buf_printf(&log_message_buf, "Branch: renamed %s to %s",
git_reference_name(branch), git_buf_cstr(&new_reference_name))) < 0)
goto done;
}
/* first update ref then config so failure won't trash config */
error = git_reference_rename(
out, branch, git_buf_cstr(&new_reference_name), force);
out, branch, git_buf_cstr(&new_reference_name), force,
signature, git_buf_cstr(&log_message_buf));
if (error < 0)
goto done;
......@@ -221,6 +246,7 @@ done:
git_buf_free(&new_reference_name);
git_buf_free(&old_config_section);
git_buf_free(&new_config_section);
git_buf_free(&log_message_buf);
return error;
}
......
......@@ -27,7 +27,9 @@ static int create_branch(
git_reference **branch,
git_repository *repo,
const git_oid *target,
const char *name)
const char *name,
const git_signature *signature,
const char *log_message)
{
git_commit *head_obj = NULL;
git_reference *branch_ref = NULL;
......@@ -38,7 +40,7 @@ static int create_branch(
return error;
/* Create the new branch */
error = git_branch_create(&branch_ref, repo, name, head_obj, 0);
error = git_branch_create(&branch_ref, repo, name, head_obj, 0, signature, log_message);
git_commit_free(head_obj);
......@@ -87,11 +89,13 @@ static int create_tracking_branch(
git_reference **branch,
git_repository *repo,
const git_oid *target,
const char *branch_name)
const char *branch_name,
const git_signature *signature,
const char *log_message)
{
int error;
if ((error = create_branch(branch, repo, target, branch_name)) < 0)
if ((error = create_branch(branch, repo, target, branch_name, signature, log_message)) < 0)
return error;
return setup_tracking_config(
......@@ -152,21 +156,29 @@ static int reference_matches_remote_head(
static int update_head_to_new_branch(
git_repository *repo,
const git_oid *target,
const char *name)
const char *name,
const git_signature *signature,
const char *reflog_message)
{
git_reference *tracking_branch = NULL;
int error = create_tracking_branch(&tracking_branch, repo, target, name);
int error = create_tracking_branch(&tracking_branch, repo, target, name,
signature, reflog_message);
if (!error)
error = git_repository_set_head(
repo, git_reference_name(tracking_branch));
repo, git_reference_name(tracking_branch),
signature, reflog_message);
git_reference_free(tracking_branch);
return error;
}
static int update_head_to_remote(git_repository *repo, git_remote *remote)
static int update_head_to_remote(
git_repository *repo,
git_remote *remote,
const git_signature *signature,
const char *reflog_message)
{
int error = 0;
size_t refs_len;
......@@ -215,7 +227,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname));
git_buf_cstr(&head_info.branchname),
signature, reflog_message);
goto cleanup;
}
......@@ -229,10 +242,11 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname));
git_buf_cstr(&head_info.branchname),
signature, reflog_message);
} else {
error = git_repository_set_head_detached(
repo, &head_info.remote_head_oid);
repo, &head_info.remote_head_oid, signature, reflog_message);
}
cleanup:
......@@ -244,7 +258,9 @@ cleanup:
static int update_head_to_branch(
git_repository *repo,
const char *remote_name,
const char *branch)
const char *branch,
const git_signature *signature,
const char *reflog_message)
{
int retcode;
git_buf remote_branch_name = GIT_BUF_INIT;
......@@ -259,7 +275,8 @@ static int update_head_to_branch(
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
goto cleanup;
retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch);
retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
signature, reflog_message);
cleanup:
git_reference_free(remote_ref);
......@@ -319,10 +336,11 @@ static bool should_checkout(
return !git_repository_head_unborn(repo);
}
int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch)
int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch, const git_signature *signature)
{
int error = 0, old_fetchhead;
git_strarray refspecs;
git_buf reflog_message = GIT_BUF_INIT;
assert(repo && remote);
......@@ -340,15 +358,17 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_
old_fetchhead = git_remote_update_fetchhead(remote);
git_remote_set_update_fetchhead(remote, 0);
git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
if ((error = git_remote_fetch(remote)) != 0)
goto cleanup;
if (branch)
error = update_head_to_branch(repo, git_remote_name(remote), branch);
error = update_head_to_branch(repo, git_remote_name(remote), branch,
signature, git_buf_cstr(&reflog_message));
/* Point HEAD to the same ref as the remote's head */
else
error = update_head_to_remote(repo, remote);
error = update_head_to_remote(repo, remote, signature, git_buf_cstr(&reflog_message));
if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts))
error = git_checkout_head(repo, co_opts);
......@@ -364,6 +384,7 @@ cleanup:
}
git_strarray_free(&refspecs);
git_buf_free(&reflog_message);
return error;
}
......@@ -403,7 +424,7 @@ int git_clone(
if (!(error = create_and_configure_origin(&origin, repo, url, &options))) {
error = git_clone_into(
repo, origin, &options.checkout_opts, options.checkout_branch);
repo, origin, &options.checkout_opts, options.checkout_branch, options.signature);
git_remote_free(origin);
}
......
......@@ -1434,12 +1434,14 @@ success:
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_signature *who, const char *message)
{
int error;
git_oid old_id, new_id;
git_oid old_id, new_id = {{0}};
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
git_repository *repo = backend->repo;
/* Creation of symbolic references doesn't get a reflog entry */
if (ref->type == GIT_REF_SYMBOLIC)
/* Creation of a symbolic reference doesn't get a reflog entry, except for
* HEAD. git_repository_set_head and friends go through here. */
if (ref->type == GIT_REF_SYMBOLIC &&
0 != strcmp(ref->name, GIT_HEAD_FILE))
return 0;
error = git_reference_name_to_id(&old_id, repo, ref->name);
......@@ -1450,7 +1452,8 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
if (error < 0)
return error;
git_oid_cpy(&new_id, git_reference_target(ref));
if (git_reference_target(ref) != NULL)
git_oid_cpy(&new_id, git_reference_target(ref));
if ((error = serialize_reflog_entry(&buf, &old_id, &new_id, who, message)) < 0)
goto cleanup;
......
......@@ -545,7 +545,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char
/* Update HEAD it was pointing to the reference being renamed */
if (should_head_be_updated &&
(error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
(error = git_repository_set_head(ref->db->repo, new_name, signature, message)) < 0) {
giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
return error;
}
......@@ -558,35 +558,28 @@ int git_reference_rename(
git_reference **out,
git_reference *ref,
const char *new_name,
int force)
int force,
const git_signature *signature,
const char *log_message)
{
git_signature *who;
git_signature *who = (git_signature*)signature;
int error;
/* Should we return an error if there is no default? */
if (((error = git_signature_default(&who, ref->db->repo)) < 0) &&
if (!who &&
((error = git_signature_default(&who, ref->db->repo)) < 0) &&
((error = git_signature_now(&who, "unknown", "unknown")) < 0)) {
return error;
}
error = reference__rename(out, ref, new_name, force, who, NULL);
error = reference__rename(out, ref, new_name, force, who, log_message);
git_signature_free(who);
if (!signature)
git_signature_free(who);
return error;
}
int git_reference_rename_with_log(
git_reference **out,
git_reference *ref,
const char *new_name,
int force,
const git_signature *who,
const char * message)
{
return reference__rename(out, ref, new_name, force, who, message);
}
int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
{
switch (git_reference_type(ref)) {
......
......@@ -1332,20 +1332,28 @@ static int rename_one_remote_reference(
{
int error;
git_buf new_name = GIT_BUF_INIT;
git_buf log_message = GIT_BUF_INIT;
error = git_buf_printf(
&new_name,
GIT_REFS_REMOTES_DIR "%s%s",
new_remote_name,
reference->name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name));
if ((error = git_buf_printf(
&new_name,
GIT_REFS_REMOTES_DIR "%s%s",
new_remote_name,
reference->name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name))) < 0)
goto cleanup;
if (!error) {
error = git_reference_rename(
NULL, reference, git_buf_cstr(&new_name), 0);
git_reference_free(reference);
}
if ((error = git_buf_printf(&log_message,
"renamed remote %s to %s",
old_remote_name, new_remote_name)) < 0)
goto cleanup;
error = git_reference_rename(
NULL, reference, git_buf_cstr(&new_name), 0,
NULL, git_buf_cstr(&log_message));
git_reference_free(reference);
cleanup:
git_buf_free(&new_name);
git_buf_free(&log_message);
return error;
}
......
......@@ -1830,7 +1830,9 @@ static bool looks_like_a_branch(const char *refname)
int git_repository_set_head(
git_repository* repo,
const char* refname)
const char* refname,
const git_signature *signature,
const char *log_message)
{
git_reference *ref,
*new_head = NULL;
......@@ -1843,12 +1845,17 @@ int git_repository_set_head(
return error;
if (!error) {
if (git_reference_is_branch(ref))
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, git_reference_name(ref), 1, NULL, NULL);
else
error = git_repository_set_head_detached(repo, git_reference_target(ref));
} else if (looks_like_a_branch(refname))
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname, 1, NULL, NULL);
if (git_reference_is_branch(ref)) {
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
git_reference_name(ref), true, signature, log_message);
} else {
error = git_repository_set_head_detached(repo, git_reference_target(ref),
signature, log_message);
}
} else if (looks_like_a_branch(refname)) {
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
true, signature, log_message);
}
git_reference_free(ref);
git_reference_free(new_head);
......@@ -1857,7 +1864,9 @@ int git_repository_set_head(
int git_repository_set_head_detached(
git_repository* repo,
const git_oid* commitish)
const git_oid* commitish,
const git_signature *signature,
const char *log_message)
{
int error;
git_object *object,
......@@ -1872,7 +1881,7 @@ int git_repository_set_head_detached(
if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
goto cleanup;
error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), 1, NULL, NULL);
error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, signature, log_message);
cleanup:
git_object_free(object);
......
......@@ -63,7 +63,7 @@ void test_checkout_tree__can_checkout_and_remove_directory(void)
cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees"));
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert_equal_i(true, git_path_isdir("./testrepo/ab/"));
cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt"));
......@@ -78,7 +78,7 @@ void test_checkout_tree__can_checkout_and_remove_directory(void)
cl_git_pass(git_revparse_single(&g_object, g_repo, "master"));
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master", NULL, NULL));
/* This directory should no longer exist */
cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
......@@ -163,7 +163,7 @@ void test_checkout_tree__can_switch_branches(void)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir", NULL, NULL));
cl_assert(git_path_isfile("testrepo/README"));
cl_assert(git_path_isfile("testrepo/branch_file.txt"));
......@@ -183,7 +183,7 @@ void test_checkout_tree__can_switch_branches(void)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert(git_path_isfile("testrepo/README"));
cl_assert(git_path_isfile("testrepo/branch_file.txt"));
......@@ -253,7 +253,7 @@ static int checkout_tree_with_blob_ignored_in_workdir(int strategy, bool isdir)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir", NULL, NULL));
cl_assert(git_path_isfile("testrepo/README"));
cl_assert(git_path_isfile("testrepo/branch_file.txt"));
......@@ -313,7 +313,7 @@ void test_checkout_tree__can_overwrite_ignored_by_default(void)
{
cl_git_pass(checkout_tree_with_blob_ignored_in_workdir(GIT_CHECKOUT_SAFE, false));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert(git_path_isfile("testrepo/ab/4.txt"));
......@@ -334,7 +334,7 @@ void test_checkout_tree__can_overwrite_ignored_folder_by_default(void)
{
cl_git_pass(checkout_tree_with_blob_ignored_in_workdir(GIT_CHECKOUT_SAFE, true));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees", NULL, NULL));
cl_assert(git_path_isfile("testrepo/ab/4.txt"));
......@@ -367,7 +367,7 @@ void test_checkout_tree__can_update_only(void)
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir", NULL, NULL));
assert_on_branch(g_repo, "dir");
......@@ -396,7 +396,7 @@ void test_checkout_tree__can_checkout_with_pattern(void)
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
cl_git_pass(
git_repository_set_head_detached(g_repo, git_object_id(g_object)));
git_repository_set_head_detached(g_repo, git_object_id(g_object), NULL, NULL));
git_object_free(g_object);
g_object = NULL;
......@@ -435,7 +435,7 @@ void test_checkout_tree__can_disable_pattern_match(void)
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
cl_git_pass(
git_repository_set_head_detached(g_repo, git_object_id(g_object)));
git_repository_set_head_detached(g_repo, git_object_id(g_object), NULL, NULL));
git_object_free(g_object);
g_object = NULL;
......@@ -480,7 +480,7 @@ void assert_conflict(
/* Create a branch pointing at the parent */
cl_git_pass(git_revparse_single(&g_object, g_repo, parent_sha));
cl_git_pass(git_branch_create(&branch, g_repo,
"potential_conflict", (git_commit *)g_object, 0));
"potential_conflict", (git_commit *)g_object, 0, NULL, NULL));
/* Make HEAD point to this branch */
cl_git_pass(git_reference_symbolic_create(
......@@ -687,7 +687,7 @@ void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void)
cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id));
cl_git_pass(git_checkout_tree(g_repo, (git_object *)commit, &opts));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master", NULL, NULL));
cl_git_pass(p_mkdir("./testrepo/this-is-dir", 0777));
cl_git_mkfile("./testrepo/this-is-dir/contained_file", "content\n");
......
......@@ -122,7 +122,7 @@ void test_checkout_typechange__checkout_typechanges_safe(void)
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
cl_git_pass(
git_repository_set_head_detached(g_repo, git_object_id(obj)));
git_repository_set_head_detached(g_repo, git_object_id(obj), NULL, NULL));
assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);
......@@ -231,7 +231,7 @@ void test_checkout_typechange__checkout_with_conflicts(void)
cl_assert(!git_path_exists("typechanges/untracked"));
cl_git_pass(
git_repository_set_head_detached(g_repo, git_object_id(obj)));
git_repository_set_head_detached(g_repo, git_object_id(obj), NULL, NULL));
assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);
......
......@@ -24,6 +24,7 @@ void test_clone_nonetwork__initialize(void)
g_options.checkout_opts = dummy_opts;
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
g_options.remote_callbacks = dummy_callbacks;
cl_git_pass(git_signature_now(&g_options.signature, "Me", "foo@example.com"));
}
void test_clone_nonetwork__cleanup(void)
......@@ -43,6 +44,7 @@ void test_clone_nonetwork__cleanup(void)
g_remote = NULL;
}
git_signature_free(g_options.signature);
cl_fixture_cleanup("./foo");
}
......@@ -213,11 +215,13 @@ void test_clone_nonetwork__can_detached_head(void)
git_object *obj;
git_repository *cloned;
git_reference *cloned_head;
git_reflog *log;
const git_reflog_entry *entry;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_revparse_single(&obj, g_repo, "master~1"));
cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj)));
cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj), NULL, NULL));
cl_git_pass(git_clone(&cloned, "./foo", "./foo1", &g_options));
......@@ -226,9 +230,55 @@ void test_clone_nonetwork__can_detached_head(void)
cl_git_pass(git_repository_head(&cloned_head, cloned));
cl_assert(!git_oid_cmp(git_object_id(obj), git_reference_target(cloned_head)));
cl_git_pass(git_reflog_read(&log, cloned, "HEAD"));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
git_object_free(obj);
git_reference_free(cloned_head);
git_reflog_free(log);
git_repository_free(cloned);
cl_fixture_cleanup("./foo1");
}
static void assert_correct_reflog(const char *name)
{
git_reflog *log;
const git_reflog_entry *entry;
char expected_log_message[128] = {0};
sprintf(expected_log_message, "clone: from %s", cl_git_fixture_url("testrepo.git"));
cl_git_pass(git_reflog_read(&log, g_repo, name));
cl_assert_equal_i(1, git_reflog_entrycount(log));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s(expected_log_message, git_reflog_entry_message(entry));
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
git_reflog_free(log);
}
void test_clone_nonetwork__clone_updates_reflog_properly(void)
{
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
assert_correct_reflog("HEAD");
assert_correct_reflog("refs/heads/master");
}
void test_clone_nonetwork__clone_into_updates_reflog_properly(void)
{
git_remote *remote;
git_signature *sig;
cl_git_pass(git_signature_now(&sig, "Me", "foo@example.com"));
cl_git_pass(git_repository_init(&g_repo, "./foo", false));
cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_git_fixture_url("testrepo.git")));
cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, sig));
assert_correct_reflog("HEAD");
assert_correct_reflog("refs/heads/master");
git_remote_free(remote);
git_signature_free(sig);
}
......@@ -147,7 +147,7 @@ void test_online_clone__clone_into(void)
callbacks.payload = &fetch_progress_cb_was_called;
git_remote_set_callbacks(remote, &callbacks);
cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL));
cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL, NULL));
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
......
......@@ -46,7 +46,7 @@ void test_refs_branches_create__can_create_a_local_branch(void)
{
retrieve_known_commit(&target, repo);
cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, 0));
cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, 0, NULL, NULL));
cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target)));
}
......@@ -54,24 +54,69 @@ void test_refs_branches_create__can_not_create_a_branch_if_its_name_collide_with
{
retrieve_known_commit(&target, repo);
cl_assert_equal_i(GIT_EEXISTS, git_branch_create(&branch, repo, "br2", target, 0));
cl_assert_equal_i(GIT_EEXISTS, git_branch_create(&branch, repo, "br2", target, 0, NULL, NULL));
}
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, repo, "br2", target, 1));
cl_git_pass(git_branch_create(&branch, repo, "br2", target, 1, NULL, NULL));
cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target)));
cl_assert_equal_s("refs/heads/br2", git_reference_name(branch));
}
void test_refs_branches_create__creating_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void)
{
retrieve_known_commit(&target, repo);
cl_assert_equal_i(GIT_EINVALIDSPEC,
git_branch_create(&branch, repo, "inv@{id", target, 0));
git_branch_create(&branch, repo, "inv@{id", target, 0, NULL, NULL));
}
void test_refs_branches_create__creation_creates_new_reflog(void)
{
git_reflog *log;
const git_reflog_entry *entry;
git_signature *sig;
cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
retrieve_known_commit(&target, repo);
cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, sig, "create!"));
cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));
cl_assert_equal_i(1, git_reflog_entrycount(log));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("create!", git_reflog_entry_message(entry));
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
git_reflog_free(log);
git_signature_free(sig);
}
void test_refs_branches_create__default_reflog_message(void)
{
git_reflog *log;
const git_reflog_entry *entry;
git_signature *sig;
git_config *cfg;
cl_git_pass(git_repository_config(&cfg, repo));
cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar"));
cl_git_pass(git_config_set_string(cfg, "user.email", "foo@example.com"));
git_config_free(cfg);
cl_git_pass(git_signature_default(&sig, repo));
retrieve_known_commit(&target, repo);
cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, NULL, NULL));
cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("Branch: created", git_reflog_entry_message(entry));
cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);
git_reflog_free(log);
git_signature_free(sig);
}
......@@ -115,3 +115,29 @@ void test_refs_branches_delete__deleting_a_branch_removes_related_configuration_
assert_config_entry_existence(repo, "branch.track-local.remote", false);
assert_config_entry_existence(repo, "branch.track-local.merge", false);
}
void test_refs_branches_delete__removes_reflog(void)
{
git_reference *branch;
git_reflog *log;
git_oid oidzero = {{0}};
git_signature *sig;
/* Ensure the reflog has at least one entry */
cl_git_pass(git_signature_now(&sig, "Me", "user@example.com"));
cl_git_pass(git_reflog_read(&log, repo, "refs/heads/track-local"));
cl_git_pass(git_reflog_append(log, &oidzero, sig, "message"));
cl_assert(git_reflog_entrycount(log) > 0);
git_signature_free(sig);
git_reflog_free(log);
cl_git_pass(git_branch_lookup(&branch, repo, "track-local", GIT_BRANCH_LOCAL));
cl_git_pass(git_branch_delete(branch));
git_reference_free(branch);
/* Reading a nonexistant reflog creates it, but it should be empty */
cl_git_pass(git_reflog_read(&log, repo, "refs/heads/track-local"));
cl_assert_equal_i(0, git_reflog_entrycount(log));
git_reflog_free(log);
}
......@@ -22,7 +22,7 @@ void test_refs_branches_move__can_move_a_local_branch(void)
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
cl_git_pass(git_branch_move(&new_ref, original_ref, NEW_BRANCH_NAME, 0));
cl_git_pass(git_branch_move(&new_ref, original_ref, NEW_BRANCH_NAME, 0, NULL, NULL));
cl_assert_equal_s(GIT_REFS_HEADS_DIR NEW_BRANCH_NAME, git_reference_name(new_ref));
git_reference_free(original_ref);
......@@ -36,11 +36,11 @@ void test_refs_branches_move__can_move_a_local_branch_to_a_different_namespace(v
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
/* Downward */
cl_git_pass(git_branch_move(&new_ref, original_ref, "somewhere/" NEW_BRANCH_NAME, 0));
cl_git_pass(git_branch_move(&new_ref, original_ref, "somewhere/" NEW_BRANCH_NAME, 0, NULL, NULL));
git_reference_free(original_ref);
/* Upward */
cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0));
cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0, NULL, NULL));
git_reference_free(new_ref);
git_reference_free(newer_ref);
......@@ -53,11 +53,11 @@ void test_refs_branches_move__can_move_a_local_branch_to_a_partially_colliding_n
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
/* Downward */
cl_git_pass(git_branch_move(&new_ref, original_ref, "br2/" NEW_BRANCH_NAME, 0));
cl_git_pass(git_branch_move(&new_ref, original_ref, "br2/" NEW_BRANCH_NAME, 0, NULL, NULL));
git_reference_free(original_ref);
/* Upward */
cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0));
cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0, NULL, NULL));
git_reference_free(new_ref);
git_reference_free(newer_ref);
......@@ -81,7 +81,7 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
cl_assert_equal_i(GIT_EEXISTS,
git_branch_move(&new_ref, original_ref, "master", 0));
git_branch_move(&new_ref, original_ref, "master", 0, NULL, NULL));
cl_assert(giterr_last()->message != NULL);
cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote"));
......@@ -91,7 +91,7 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
cl_assert_equal_i(GIT_EEXISTS,
git_branch_move(&new_ref, original_ref, "cannot-fetch", 0));
git_branch_move(&new_ref, original_ref, "cannot-fetch", 0, NULL, NULL));
cl_assert(giterr_last()->message != NULL);
cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote"));
......@@ -103,7 +103,7 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/track-local"));
cl_assert_equal_i(GIT_EEXISTS,
git_branch_move(&new_ref, original_ref, "master", 0));
git_branch_move(&new_ref, original_ref, "master", 0, NULL, NULL));
cl_assert(giterr_last()->message != NULL);
cl_git_pass(git_config_get_entry(&ce, config, "branch.master.remote"));
......@@ -122,7 +122,7 @@ void test_refs_branches_move__moving_a_branch_with_an_invalid_name_returns_EINVA
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_move(&new_ref, original_ref, "Inv@{id", 0));
cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_move(&new_ref, original_ref, "Inv@{id", 0, NULL, NULL));
git_reference_free(original_ref);
}
......@@ -132,7 +132,7 @@ void test_refs_branches_move__can_not_move_a_non_branch(void)
git_reference *tag, *new_ref;
cl_git_pass(git_reference_lookup(&tag, repo, "refs/tags/e90810b"));
cl_git_fail(git_branch_move(&new_ref, tag, NEW_BRANCH_NAME, 0));
cl_git_fail(git_branch_move(&new_ref, tag, NEW_BRANCH_NAME, 0, NULL, NULL));
git_reference_free(tag);
}
......@@ -143,7 +143,7 @@ void test_refs_branches_move__can_force_move_over_an_existing_branch(void)
cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2"));
cl_git_pass(git_branch_move(&new_ref, original_ref, "master", 1));
cl_git_pass(git_branch_move(&new_ref, original_ref, "master", 1, NULL, NULL));
git_reference_free(original_ref);
git_reference_free(new_ref);
......@@ -161,7 +161,7 @@ void test_refs_branches_move__moving_a_branch_moves_related_configuration_data(v
assert_config_entry_existence(repo, "branch.moved.remote", false);
assert_config_entry_existence(repo, "branch.moved.merge", false);
cl_git_pass(git_branch_move(&new_branch, branch, "moved", 0));
cl_git_pass(git_branch_move(&new_branch, branch, "moved", 0, NULL, NULL));
git_reference_free(branch);
assert_config_entry_existence(repo, "branch.track-local.remote", false);
......@@ -178,7 +178,7 @@ void test_refs_branches_move__moving_the_branch_pointed_at_by_HEAD_updates_HEAD(
git_reference *new_branch;
cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0));
cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0, NULL, NULL));
git_reference_free(branch);
git_reference_free(new_branch);
......@@ -186,3 +186,58 @@ void test_refs_branches_move__moving_the_branch_pointed_at_by_HEAD_updates_HEAD(
cl_assert_equal_s("refs/heads/master2", git_reference_name(branch));
git_reference_free(branch);
}
void test_refs_branches_move__updates_the_reflog(void)
{
git_reference *branch;
git_reference *new_branch;
git_reflog *log;
const git_reflog_entry *entry;
git_signature *sig;
cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0, sig, "message"));
cl_git_pass(git_reflog_read(&log, repo, git_reference_name(new_branch)));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("message", git_reflog_entry_message(entry));
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
git_reference_free(branch);
git_reference_free(new_branch);
git_reflog_free(log);
git_signature_free(sig);
}
void test_refs_branches_move__default_reflog_message(void)
{
git_reference *branch;
git_reference *new_branch;
git_reflog *log;
const git_reflog_entry *entry;
git_signature *sig;
git_config *cfg;
cl_git_pass(git_repository_config(&cfg, repo));
cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar"));
cl_git_pass(git_config_set_string(cfg, "user.email", "foo@example.com"));
git_config_free(cfg);
cl_git_pass(git_signature_default(&sig, repo));
cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0, NULL, NULL));
cl_git_pass(git_reflog_read(&log, repo, git_reference_name(new_branch)));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("Branch: renamed refs/heads/master to refs/heads/master2",
git_reflog_entry_message(entry));
cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);
git_reference_free(branch);
git_reference_free(new_branch);
git_reflog_free(log);
git_signature_free(sig);
}
......@@ -66,7 +66,7 @@ static void assert_merge_and_or_remote_key_missing(git_repository *repository, c
git_reference *branch;
cl_assert_equal_i(GIT_OBJ_COMMIT, git_object_type((git_object*)target));
cl_git_pass(git_branch_create(&branch, repository, entry_name, (git_commit*)target, 0));
cl_git_pass(git_branch_create(&branch, repository, entry_name, (git_commit*)target, 0, NULL, NULL));
cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch));
......
......@@ -114,7 +114,7 @@ void test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog(void)
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&moved_log_path)));
cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master"));
cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0));
cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0, NULL, NULL));
git_reference_free(master);
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&master_log_path)));
......@@ -165,7 +165,7 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void)
cl_git_pass(git_reflog_write(reflog));
cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0));
cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0, NULL, NULL));
git_reference_free(master);
cl_git_fail(git_reflog_write(reflog));
......
......@@ -49,7 +49,7 @@ void test_refs_rename__loose(void)
cl_assert(reference_is_packed(looked_up_ref) == 0);
/* Now that the reference is renamed... */
cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, new_name, 0));
cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, new_name, 0, NULL, NULL));
cl_assert_equal_s(new_ref->name, new_name);
git_reference_free(looked_up_ref);
......@@ -91,7 +91,7 @@ void test_refs_rename__packed(void)
cl_assert(reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, brand_new_name, 0));
cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, brand_new_name, 0, NULL, NULL));
cl_assert_equal_s(new_ref->name, brand_new_name);
git_reference_free(looked_up_ref);
......@@ -140,7 +140,7 @@ void test_refs_rename__packed_doesnt_pack_others(void)
cl_assert(reference_is_packed(looked_up_ref) != 0);
/* Now that the reference is renamed... */
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, brand_new_name, 0));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, brand_new_name, 0, NULL, NULL));
git_reference_free(looked_up_ref);
/* Lookup the other reference */
......@@ -166,7 +166,7 @@ void test_refs_rename__name_collision(void)
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
/* Can not be renamed to the name of another existing reference. */
cl_git_fail(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 0));
cl_git_fail(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 0, NULL, NULL));
git_reference_free(looked_up_ref);
/* Failure to rename it hasn't corrupted its state */
......@@ -187,12 +187,12 @@ void test_refs_rename__invalid_name(void)
/* Can not be renamed with an invalid name. */
cl_assert_equal_i(
GIT_EINVALIDSPEC,
git_reference_rename(&renamed_ref, looked_up_ref, "Hello! I'm a very invalid name.", 0));
git_reference_rename(&renamed_ref, looked_up_ref, "Hello! I'm a very invalid name.", 0, NULL, NULL));
/* Can not be renamed outside of the refs hierarchy
* unless it's ALL_CAPS_AND_UNDERSCORES.
*/
cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(&renamed_ref, looked_up_ref, "i-will-sudo-you", 0));
cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(&renamed_ref, looked_up_ref, "i-will-sudo-you", 0, NULL, NULL));
/* Failure to rename it hasn't corrupted its state */
git_reference_free(looked_up_ref);
......@@ -213,7 +213,7 @@ void test_refs_rename__force_loose_packed(void)
git_oid_cpy(&oid, git_reference_target(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 1));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 1, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
......@@ -238,7 +238,7 @@ void test_refs_rename__force_loose(void)
git_oid_cpy(&oid, git_reference_target(looked_up_ref));
/* Can be force-renamed to the name of another existing reference. */
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, "refs/heads/test", 1));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, "refs/heads/test", 1, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
......@@ -307,7 +307,7 @@ void test_refs_rename__prefix(void)
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
/* Can be rename to a new name starting with the old name. */
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name_new, 0));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name_new, 0, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
......@@ -341,7 +341,7 @@ void test_refs_rename__move_up(void)
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
/* Can be renamed upward the reference tree. */
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name, 0));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name, 0, NULL, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
......@@ -361,7 +361,30 @@ void test_refs_rename__propagate_eexists(void)
cl_git_pass(git_reference_lookup(&ref, g_repo, packed_head_name));
cl_assert_equal_i(GIT_EEXISTS, git_reference_rename(&new_ref, ref, packed_test_head_name, 0));
cl_assert_equal_i(GIT_EEXISTS, git_reference_rename(&new_ref, ref, packed_test_head_name, 0, NULL, NULL));
git_reference_free(ref);
}
void test_refs_rename__writes_to_reflog(void)
{
git_reference *ref, *new_ref;
git_reflog *log;
const git_reflog_entry *entry;
git_signature *sig;
cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_git_pass(git_reference_rename(&new_ref, ref, ref_one_name_new, false,
sig, "message"));
cl_git_pass(git_reflog_read(&log, g_repo, git_reference_name(new_ref)));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("message", git_reflog_entry_message(entry));
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
git_reflog_free(log);
git_reference_free(ref);
git_reference_free(new_ref);
git_signature_free(sig);
}
......@@ -325,7 +325,7 @@ static void create_fake_stash_reference_and_reflog(git_repository *repo)
cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&log_path)));
cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master"));
cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0));
cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0, NULL, NULL));
git_reference_free(master);
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path)));
......@@ -634,7 +634,7 @@ void test_refs_revparse__try_to_retrieve_branch_before_described_tag(void)
test_object_inrepo("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo);
cl_git_pass(git_revparse_single(&target, repo, "HEAD~3"));
cl_git_pass(git_branch_create(&branch, repo, "blah-7-gc47800c", (git_commit *)target, 0));
cl_git_pass(git_branch_create(&branch, repo, "blah-7-gc47800c", (git_commit *)target, 0, NULL, NULL));
git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target));
......@@ -672,7 +672,7 @@ void test_refs_revparse__try_to_retrieve_sha_before_branch(void)
test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo);
cl_git_pass(git_revparse_single(&target, repo, "HEAD~3"));
cl_git_pass(git_branch_create(&branch, repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0));
cl_git_pass(git_branch_create(&branch, repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0, NULL, NULL));
git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target));
......@@ -708,7 +708,7 @@ void test_refs_revparse__try_to_retrieve_branch_before_abbrev_sha(void)
test_object_inrepo("c47800", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo);
cl_git_pass(git_revparse_single(&target, repo, "HEAD~3"));
cl_git_pass(git_branch_create(&branch, repo, "c47800", (git_commit *)target, 0));
cl_git_pass(git_branch_create(&branch, repo, "c47800", (git_commit *)target, 0, NULL, NULL));
git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target));
......
......@@ -54,7 +54,7 @@ void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_
{
git_reference *head;
cl_git_pass(git_repository_set_head(repo, "refs/heads/doesnt/exist/yet"));
cl_git_pass(git_repository_set_head(repo, "refs/heads/doesnt/exist/yet", NULL, NULL));
cl_assert_equal_i(false, git_repository_head_detached(repo));
......@@ -63,19 +63,19 @@ void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_
void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist(void)
{
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head(repo, "refs/tags/doesnt/exist/yet"));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head(repo, "refs/tags/doesnt/exist/yet", NULL, NULL));
}
void test_repo_head__set_head_Fails_when_the_reference_points_to_a_non_commitish(void)
{
cl_git_fail(git_repository_set_head(repo, "refs/tags/point_to_blob"));
cl_git_fail(git_repository_set_head(repo, "refs/tags/point_to_blob", NULL, NULL));
}
void test_repo_head__set_head_Attaches_HEAD_when_the_reference_points_to_a_branch(void)
{
git_reference *head;
cl_git_pass(git_repository_set_head(repo, "refs/heads/br2"));
cl_git_pass(git_repository_set_head(repo, "refs/heads/br2", NULL, NULL));
cl_assert_equal_i(false, git_repository_head_detached(repo));
......@@ -102,7 +102,7 @@ static void assert_head_is_correctly_detached(void)
void test_repo_head__set_head_Detaches_HEAD_when_the_reference_doesnt_point_to_a_branch(void)
{
cl_git_pass(git_repository_set_head(repo, "refs/tags/test"));
cl_git_pass(git_repository_set_head(repo, "refs/tags/test", NULL, NULL));
cl_assert_equal_i(true, git_repository_head_detached(repo));
......@@ -115,7 +115,7 @@ void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_e
cl_git_pass(git_oid_fromstr(&oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid, NULL, NULL));
}
void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(void)
......@@ -124,7 +124,7 @@ void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(vo
cl_git_pass(git_revparse_single(&blob, repo, "point_to_blob"));
cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob)));
cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob), NULL, NULL));
git_object_free(blob);
}
......@@ -136,7 +136,7 @@ void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_pe
cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
cl_assert_equal_i(GIT_OBJ_TAG, git_object_type(tag));
cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag)));
cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag), NULL, NULL));
assert_head_is_correctly_detached();
......@@ -194,3 +194,54 @@ void test_repo_head__can_tell_if_an_unborn_head_is_detached(void)
cl_assert_equal_i(false, git_repository_head_detached(repo));
}
void test_repo_head__setting_head_updates_reflog(void)
{
git_reflog *log;
const git_reflog_entry *entry1, *entry2, *entry3;
git_object *tag;
git_signature *sig;
cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, "message1"));
cl_git_pass(git_repository_set_head(repo, "refs/heads/unborn", sig, "message2"));
cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag), sig, "message3"));
cl_git_pass(git_reflog_read(&log, repo, "HEAD"));
entry1 = git_reflog_entry_byindex(log, 2);
entry2 = git_reflog_entry_byindex(log, 1);
entry3 = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("message1", git_reflog_entry_message(entry1));
cl_assert_equal_s("message2", git_reflog_entry_message(entry2));
cl_assert_equal_s("message3", git_reflog_entry_message(entry3));
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry1)->email);
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry2)->email);
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry3)->email);
git_reflog_free(log);
git_object_free(tag);
git_signature_free(sig);
}
void test_repo_head__setting_creates_head_ref(void)
{
git_reference *head;
git_reflog *log;
const git_reflog_entry *entry;
cl_git_pass(git_reference_lookup(&head, repo, "HEAD"));
cl_git_pass(git_reference_delete(head));
cl_git_pass(git_reflog_delete(repo, "HEAD"));
cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", NULL, "create HEAD"));
cl_git_pass(git_reflog_read(&log, repo, "HEAD"));
cl_assert_equal_i(1, git_reflog_entrycount(log));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("create HEAD", git_reflog_entry_message(entry));
git_reflog_free(log);
git_reference_free(head);
}
......@@ -140,7 +140,7 @@ void test_status_submodules__moved_head(void)
/* move submodule HEAD to c47800c7266a2be04c571c04d5a6614691ea99bd */
cl_git_pass(
git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
cl_git_pass(git_repository_set_head_detached(smrepo, &oid));
cl_git_pass(git_repository_set_head_detached(smrepo, &oid, NULL, NULL));
/* first do a normal status, which should now include the submodule */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment