Commit a6346302e6805aea0f1c353bb62944f1ae7352af

Ben Straub 2012-05-03T13:58:46

Rev-parse: "ref@{upstream}" syntax. Added tracking configuration to the test repo's config to support unit tests.

diff --git a/src/revparse.c b/src/revparse.c
index 9719093..13778eb 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -18,6 +18,8 @@
 #include "git2/commit.h"
 #include "git2/reflog.h"
 #include "git2/refs.h"
+#include "git2/repository.h"
+#include "git2/config.h"
 
 GIT_BEGIN_DECL
 
@@ -173,7 +175,27 @@ static int walk_ref_history(git_object **out, git_repository *repo, const char *
 
       /* @{u} or @{upstream} -> upstream branch, for a tracking branch. This is stored in the config. */
       if (!strcmp(reflogspec, "@{u}") || !strcmp(reflogspec, "@{upstream}")) {
-         /* TODO */
+         git_config *cfg;
+         if (!git_repository_config(&cfg, repo)) {
+            /* Is the ref a tracking branch? */
+            const char *remote;
+            git_buf_clear(&buf);
+            git_buf_printf(&buf, "branch.%s.remote", refspec);
+            if (!git_config_get_string(cfg, git_buf_cstr(&buf), &remote)) {
+               /* Yes. Find the first merge target name. */
+               const char *mergetarget;
+               git_buf_clear(&buf);
+               git_buf_printf(&buf, "branch.%s.merge", refspec);
+               if (!git_config_get_string(cfg, git_buf_cstr(&buf), &mergetarget) &&
+                   !git__prefixcmp(mergetarget, "refs/heads/")) {
+                  /* Success. Look up the target and fetch the object. */
+                  git_buf_clear(&buf);
+                  git_buf_printf(&buf, "refs/remotes/%s/%s", remote, mergetarget+11);
+                  retcode = revparse_lookup_fully_qualifed_ref(out, repo, git_buf_cstr(&buf));
+               }
+            }
+            git_config_free(cfg);
+         }
       }
 
       /* @{N} -> Nth prior value for the ref (from reflog) */
diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c
index c5cbb87..944a18b 100644
--- a/tests-clar/refs/revparse.c
+++ b/tests-clar/refs/revparse.c
@@ -120,10 +120,10 @@ void test_refs_revparse__reflog(void)
    test_object("master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
    test_object("@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
    test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+   test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+   test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
    /* Not ready yet
    test_object("HEAD@{100 years ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
    test_object("master@{2012-4-30 10:23:20}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
-   test_object("master@{upstream}", "???");
-   test_object("master@{u}", "???");
    */
 }
diff --git a/tests-clar/resources/testrepo.git/config b/tests-clar/resources/testrepo.git/config
index 1a5aacd..b4fdac6 100644
--- a/tests-clar/resources/testrepo.git/config
+++ b/tests-clar/resources/testrepo.git/config
@@ -6,3 +6,7 @@
 [remote "test"]
 	url = git://github.com/libgit2/libgit2
 	fetch = +refs/heads/*:refs/remotes/test/*
+
+[branch "master"]
+   remote = test
+   merge = refs/heads/master
diff --git a/tests/resources/testrepo.git/refs/remotes/test/master b/tests/resources/testrepo.git/refs/remotes/test/master
new file mode 100644
index 0000000..9536ad8
--- /dev/null
+++ b/tests/resources/testrepo.git/refs/remotes/test/master
@@ -0,0 +1 @@
+be3563ae3f795b2b4353bcce3a527ad0a4f7f644