]> git.proxmox.com Git - libgit2.git/commitdiff
Teach refspec to transform destination reference to source reference
authorJameson Miller <jamill@microsoft.com>
Thu, 7 Feb 2013 19:53:52 +0000 (14:53 -0500)
committerJameson Miller <jamill@microsoft.com>
Mon, 11 Feb 2013 16:36:28 +0000 (11:36 -0500)
include/git2/refspec.h
src/refspec.c
tests-clar/network/remotes.c

index 3e83e41e2c60ac15e0cddf431b58e74b13f3a154..ec7830b7c6e750307d73e7f1c6c6d0a2f6a7445e 100644 (file)
@@ -53,7 +53,7 @@ GIT_EXTERN(int) git_refspec_force(const git_refspec *refspec);
 GIT_EXTERN(int) git_refspec_src_matches(const git_refspec *refspec, const char *refname);
 
 /**
- * Check if a refspec's destination descriptor matches a reference 
+ * Check if a refspec's destination descriptor matches a reference
  *
  * @param refspec the refspec
  * @param refname the name of the reference to check
@@ -72,6 +72,17 @@ GIT_EXTERN(int) git_refspec_dst_matches(const git_refspec *refspec, const char *
  */
 GIT_EXTERN(int) git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name);
 
+/**
+ * Transform a target reference to its source reference following the refspec's rules
+ *
+ * @param out where to store the source reference name
+ * @param outlen the size of the `out` buffer
+ * @param spec the refspec
+ * @param name the name of the reference to transform
+ * @return 0, GIT_EBUFS or another error
+ */
+GIT_EXTERN(int) git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name);
+
 GIT_END_DECL
 
 #endif
index 4f324d3c1816b1c2cbded45f14e3db6057b06898..a51b0cfab2b517f7184e1adc5253a50bbdadd89e 100644 (file)
@@ -163,15 +163,15 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
 {
        if (refspec == NULL || refspec->dst == NULL)
                return false;
-    
+
        return (p_fnmatch(refspec->dst, refname, 0) == 0);
 }
 
-int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name)
+static int refspec_transform_internal(char *out, size_t outlen, const char *from, const char *to, const char *name)
 {
        size_t baselen, namelen;
 
-       baselen = strlen(spec->dst);
+       baselen = strlen(to);
        if (outlen <= baselen) {
                giterr_set(GITERR_INVALID, "Reference name too long");
                return GIT_EBUFS;
@@ -181,8 +181,8 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
         * No '*' at the end means that it's mapped to one specific local
         * branch, so no actual transformation is needed.
         */
-       if (spec->dst[baselen - 1] != '*') {
-               memcpy(out, spec->dst, baselen + 1); /* include '\0' */
+       if (to[baselen - 1] != '*') {
+               memcpy(out, to, baselen + 1); /* include '\0' */
                return 0;
        }
 
@@ -190,7 +190,7 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
        baselen--;
 
        /* skip the prefix, -1 is for the '*' */
-       name += strlen(spec->src) - 1;
+       name += strlen(from) - 1;
 
        namelen = strlen(name);
 
@@ -199,12 +199,22 @@ int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, con
                return GIT_EBUFS;
        }
 
-       memcpy(out, spec->dst, baselen);
+       memcpy(out, to, baselen);
        memcpy(out + baselen, name, namelen + 1);
 
        return 0;
 }
 
+int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name)
+{
+       return refspec_transform_internal(out, outlen, spec->src, spec->dst, name);
+}
+
+int git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name)
+{
+       return refspec_transform_internal(out, outlen, spec->dst, spec->src, name);
+}
+
 static int refspec_transform(git_buf *out, const char *from, const char *to, const char *name)
 {
        if (git_buf_sets(out, to) < 0)
index b138d8c106a49e8498726197f02ba935d51fb01f..51d6c946f54d0113858d78f7767132309b8c69d7 100644 (file)
@@ -173,13 +173,20 @@ void test_network_remotes__fnmatch(void)
 
 void test_network_remotes__transform(void)
 {
-       char ref[1024];
+       char ref[1024] = {0};
 
-       memset(ref, 0x0, sizeof(ref));
        cl_git_pass(git_refspec_transform(ref, sizeof(ref), _refspec, "refs/heads/master"));
        cl_assert_equal_s(ref, "refs/remotes/test/master");
 }
 
+void test_network_remotes__transform_destination_to_source(void)
+{
+       char ref[1024] = {0};
+
+       cl_git_pass(git_refspec_rtransform(ref, sizeof(ref), _refspec, "refs/remotes/test/master"));
+       cl_assert_equal_s(ref, "refs/heads/master");
+}
+
 void test_network_remotes__transform_r(void)
 {
        git_buf buf = GIT_BUF_INIT;