]> git.proxmox.com Git - libgit2.git/commitdiff
Introduce GIT_MERGE_ANALYSIS_UNBORN
authorEdward Thomson <ethomson@microsoft.com>
Tue, 18 Mar 2014 23:04:51 +0000 (16:04 -0700)
committerEdward Thomson <ethomson@microsoft.com>
Thu, 20 Mar 2014 16:25:11 +0000 (09:25 -0700)
include/git2/merge.h
src/merge.c
tests/merge/workdir/analysis.c

index 2cb8df36cd54d47d4490f19d2c6c7178f1973555..491f831f8d1b5edcdf0fe022080ae8df02c88c15 100644 (file)
@@ -259,6 +259,13 @@ typedef enum {
         * given merge input.
         */
        GIT_MERGE_ANALYSIS_FASTFORWARD = (1 << 2),
+
+       /**
+        * The HEAD of the current repository is "unborn" and does not point to
+        * a valid commit.  No merge can be performed, but the caller may wish
+        * to simply set HEAD to the target commit(s).
+        */
+       GIT_MERGE_ANALYSIS_UNBORN = (1 << 3),
 } git_merge_analysis_t;
 
 /**
index 6b416a3efb7a9c040f51c26ca1af7052f693e21b..852043cd74e1cc93fbb88ff3eb0ef9d8a6636f06 100644 (file)
@@ -2524,26 +2524,41 @@ int git_merge_analysis(
        size_t their_heads_len)
 {
        git_merge_head *ancestor_head = NULL, *our_head = NULL;
-       int error;
+       int error = 0;
 
        assert(out && repo && their_heads);
 
-       *out = GIT_MERGE_ANALYSIS_NORMAL;
+       *out = GIT_MERGE_ANALYSIS_NONE;
+
+       if (git_repository_head_unborn(repo)) {
+               *out = GIT_MERGE_ANALYSIS_UNBORN;
+               goto done;
+       }
+
+       if (their_heads_len != 1) {
+               giterr_set(GITERR_MERGE, "Can only merge a single branch");
+               error = -1;
+               goto done;
+       }
 
        if ((error = merge_heads(&ancestor_head, &our_head, repo, their_heads, their_heads_len)) < 0)
                goto done;
 
-       if (their_heads_len == 1 && ancestor_head != NULL) {
-               /* We're up-to-date if we're trying to merge our own common ancestor. */
-               if (git_oid_equal(&ancestor_head->oid, &their_heads[0]->oid))
-                       *out = GIT_MERGE_ANALYSIS_UP_TO_DATE;
+       /* We're up-to-date if we're trying to merge our own common ancestor. */
+       if (ancestor_head && git_oid_equal(&ancestor_head->oid, &their_heads[0]->oid))
+               *out = GIT_MERGE_ANALYSIS_UP_TO_DATE;
 
-               /* We're fastforwardable if we're our own common ancestor. */
-               else if (git_oid_equal(&ancestor_head->oid, &our_head->oid))
-                       *out = GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_NORMAL;
-       }
+       /* We're fastforwardable if we're our own common ancestor. */
+       else if (ancestor_head && git_oid_equal(&ancestor_head->oid, &our_head->oid))
+               *out = GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_NORMAL;
+
+       /* Otherwise, just a normal merge is possible. */
+       else
+               *out = GIT_MERGE_ANALYSIS_NORMAL;
 
 done:
+       git_merge_head_free(ancestor_head);
+       git_merge_head_free(our_head);
        return error;
 }
 
index 6a4b86d266b9f345b16ea4c8212dd9f4696fb186..86b50b7183739b9880e33a3d9abdd2a7ba703c43 100644 (file)
@@ -5,6 +5,7 @@
 #include "merge.h"
 #include "../merge_helpers.h"
 #include "refs.h"
+#include "posix.h"
 
 static git_repository *repo;
 static git_index *repo_index;
@@ -39,18 +40,18 @@ static git_merge_analysis_t analysis_from_branch(const char *branchname)
 {
        git_buf refname = GIT_BUF_INIT;
        git_reference *their_ref;
-       git_merge_head *their_heads[1];
+       git_merge_head *their_head;
        git_merge_analysis_t analysis;
 
        git_buf_printf(&refname, "%s%s", GIT_REFS_HEADS_DIR, branchname);
 
        cl_git_pass(git_reference_lookup(&their_ref, repo, git_buf_cstr(&refname)));
-       cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref));
+       cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
 
-       cl_git_pass(git_merge_analysis(&analysis, repo, their_heads, 1));
+       cl_git_pass(git_merge_analysis(&analysis, repo, (const git_merge_head **)&their_head, 1));
 
        git_buf_free(&refname);
-       git_merge_head_free(their_heads[0]);
+       git_merge_head_free(their_head);
        git_reference_free(their_ref);
 
        return analysis;
@@ -88,3 +89,18 @@ void test_merge_workdir_analysis__uptodate_merging_prev_commit(void)
        analysis = analysis_from_branch(PREVIOUS_BRANCH);
        cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, analysis);
 }
+
+void test_merge_workdir_analysis__unborn(void)
+{
+       git_merge_analysis_t analysis;
+       git_buf master = GIT_BUF_INIT;
+
+       git_buf_joinpath(&master, git_repository_path(repo), "refs/heads/master");
+       p_unlink(git_buf_cstr(&master));
+
+       analysis = analysis_from_branch(NOFASTFORWARD_BRANCH);
+       cl_assert_equal_i(GIT_MERGE_ANALYSIS_UNBORN, analysis);
+
+       git_buf_free(&master);
+}
+