diff --git a/include/git2/branch.h b/include/git2/branch.h index 851de290a..46aef3206 100644 --- a/include/git2/branch.h +++ b/include/git2/branch.h @@ -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. diff --git a/include/git2/clone.h b/include/git2/clone.h index 59a73aa15..3e885d103 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -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 diff --git a/include/git2/refs.h b/include/git2/refs.h index b203f242b..976b7496b 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -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. diff --git a/include/git2/repository.h b/include/git2/repository.h index a0453da5c..648667cd6 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -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. diff --git a/src/branch.c b/src/branch.c index d0dc21b85..133d6f6d4 100644 --- a/src/branch.c +++ b/src/branch.c @@ -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; } diff --git a/src/clone.c b/src/clone.c index 2e9d72ab9..3443528f7 100644 --- a/src/clone.c +++ b/src/clone.c @@ -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); } diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 53c42458f..41ff01998 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -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; diff --git a/src/refs.c b/src/refs.c index 0f0a380ea..eb2c34211 100644 --- a/src/refs.c +++ b/src/refs.c @@ -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)) { diff --git a/src/remote.c b/src/remote.c index 5d35affd1..f33f5ef3c 100644 --- a/src/remote.c +++ b/src/remote.c @@ -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; } diff --git a/src/repository.c b/src/repository.c index 285d8897f..2c1b60266 100644 --- a/src/repository.c +++ b/src/repository.c @@ -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); diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index 3c731c5ae..407908ad3 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -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"); diff --git a/tests/checkout/typechange.c b/tests/checkout/typechange.c index 6cf99ac15..d88864cf3 100644 --- a/tests/checkout/typechange.c +++ b/tests/checkout/typechange.c @@ -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); diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c index 3cd5fb7f6..f00d28b7a 100644 --- a/tests/clone/nonetwork.c +++ b/tests/clone/nonetwork.c @@ -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); +} diff --git a/tests/online/clone.c b/tests/online/clone.c index be4421ae5..1222d174d 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -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))); diff --git a/tests/refs/branches/create.c b/tests/refs/branches/create.c index e4ad6683e..abe5f5940 100644 --- a/tests/refs/branches/create.c +++ b/tests/refs/branches/create.c @@ -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); +} diff --git a/tests/refs/branches/delete.c b/tests/refs/branches/delete.c index a642f8704..7d1d400c8 100644 --- a/tests/refs/branches/delete.c +++ b/tests/refs/branches/delete.c @@ -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); +} + diff --git a/tests/refs/branches/move.c b/tests/refs/branches/move.c index 9d233de1a..6c6dbbe21 100644 --- a/tests/refs/branches/move.c +++ b/tests/refs/branches/move.c @@ -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); +} diff --git a/tests/refs/branches/upstream.c b/tests/refs/branches/upstream.c index 69e55a0c5..ce3569813 100644 --- a/tests/refs/branches/upstream.c +++ b/tests/refs/branches/upstream.c @@ -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)); diff --git a/tests/refs/reflog/reflog.c b/tests/refs/reflog/reflog.c index 82b28de15..3f7d7d777 100644 --- a/tests/refs/reflog/reflog.c +++ b/tests/refs/reflog/reflog.c @@ -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)); diff --git a/tests/refs/rename.c b/tests/refs/rename.c index 120967892..88f0afd9c 100644 --- a/tests/refs/rename.c +++ b/tests/refs/rename.c @@ -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); +} diff --git a/tests/refs/revparse.c b/tests/refs/revparse.c index 522a44c82..a540f389d 100644 --- a/tests/refs/revparse.c +++ b/tests/refs/revparse.c @@ -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)); diff --git a/tests/repo/head.c b/tests/repo/head.c index 101e30f10..71cfc3c33 100644 --- a/tests/repo/head.c +++ b/tests/repo/head.c @@ -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); +} diff --git a/tests/status/submodules.c b/tests/status/submodules.c index dc7990cf1..80ff162fd 100644 --- a/tests/status/submodules.c +++ b/tests/status/submodules.c @@ -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 */