]> git.proxmox.com Git - libgit2.git/commitdiff
reflog: more comprehensive HEAD tests
authorCarlos Martín Nieto <cmn@dwim.me>
Tue, 18 Mar 2014 18:41:03 +0000 (19:41 +0100)
committerCarlos Martín Nieto <cmn@dwim.me>
Tue, 18 Mar 2014 18:58:52 +0000 (19:58 +0100)
The existing ones lack checking zeroed ids when switching back from an
unborn branch as well as what happens when detaching.

The reflog appending function mistakenly wrote zeros when dealing with a
detached HEAD. This explicitly checks for those situations and fixes
them.

src/refdb_fs.c
tests/repo/head.c

index f494afa71c56ec83008b5c51296033eb990082fc..0c30110837a29de63441bb56b9e780df802f45a7 100644 (file)
@@ -1555,7 +1555,7 @@ success:
 /* Append to the reflog, must be called under reference lock */
 static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *who, const char *message)
 {
-       int error, is_symbolic, was_symbolic = 0;
+       int error, is_symbolic, currently_exists;
        git_oid old_id = {{0}}, new_id = {{0}};
        git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
        git_repository *repo = backend->repo;
@@ -1573,14 +1573,14 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
        if (error < 0 && error != GIT_ENOTFOUND)
                return error;
 
-       if (current_ref)
-               was_symbolic = current_ref->type == GIT_REF_SYMBOLIC;
+       currently_exists = !!current_ref;
 
+       git_reference_free(current_ref);
        /* From here on is_symoblic also means that it's HEAD */
 
        if (old) {
                git_oid_cpy(&old_id, old);
-       } else if (!was_symbolic) {
+       } else if (currently_exists) {
                error = git_reference_name_to_id(&old_id, repo, ref->name);
                if (error == GIT_ENOTFOUND) {
                        memset(&old_id, 0, sizeof(git_oid));
index d88fd90d1ae7d6dc55658e168a75bb376eb68543..a246e608678dbd2fb4bd7e7e7bb3039e0e5e6940 100644 (file)
@@ -269,3 +269,75 @@ void test_repo_head__setting_head_updates_reflog(void)
        git_object_free(tag);
        git_signature_free(sig);
 }
+
+static void assert_head_reflog(git_repository *repo, size_t idx,
+                              const char *old_id, const char *new_id, const char *message)
+{
+       git_reflog *log;
+       const git_reflog_entry *entry;
+       char id_str[GIT_OID_HEXSZ + 1] = {0};
+
+       cl_git_pass(git_reflog_read(&log, repo, GIT_HEAD_FILE));
+       entry = git_reflog_entry_byindex(log, idx);
+
+       git_oid_fmt(id_str, git_reflog_entry_id_old(entry));
+       cl_assert_equal_s(old_id, id_str);
+
+       git_oid_fmt(id_str, git_reflog_entry_id_new(entry));
+       cl_assert_equal_s(new_id, id_str);
+
+       cl_assert_equal_s(message, git_reflog_entry_message(entry));
+
+       git_reflog_free(log);
+}
+
+void test_repo_head__detaching_writes_reflog(void)
+{
+       git_signature *sig;
+       git_oid id;
+       const char *msg;
+
+       cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
+
+       msg = "message1";
+       git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d");
+       cl_git_pass(git_repository_set_head_detached(repo, &id, sig, msg));
+       assert_head_reflog(repo, 0, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+                          "e90810b8df3e80c413d903f631643c716887138d", msg);
+
+       msg = "message2";
+       cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, msg));
+       assert_head_reflog(repo, 0, "e90810b8df3e80c413d903f631643c716887138d",
+                          "258f0e2a959a364e40ed6603d5d44fbb24765b10", msg);
+
+       git_signature_free(sig);
+}
+
+void test_repo_head__orphan_branch_does_not_count(void)
+{
+       git_signature *sig;
+       git_oid id;
+       const char *msg;
+
+       cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
+
+       /* Have something known */
+       msg = "message1";
+       git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d");
+       cl_git_pass(git_repository_set_head_detached(repo, &id, sig, msg));
+       assert_head_reflog(repo, 0, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+                          "e90810b8df3e80c413d903f631643c716887138d", msg);
+
+       /* Switching to an orphan branch does not write tot he reflog */
+       cl_git_pass(git_repository_set_head(repo, "refs/heads/orphan", sig, "ignored message"));
+       assert_head_reflog(repo, 0, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+                          "e90810b8df3e80c413d903f631643c716887138d", msg);
+
+       /* And coming back, we set the source to zero */
+       msg = "message2";
+       cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked", sig, msg));
+       assert_head_reflog(repo, 0, "0000000000000000000000000000000000000000",
+                          "258f0e2a959a364e40ed6603d5d44fbb24765b10", msg);
+
+       git_signature_free(sig);
+}