From db4bb4158f1005267e8d0e5785cb75487440580a Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Thu, 7 Feb 2013 14:53:52 -0500 Subject: [PATCH] Teach refspec to transform destination reference to source reference --- include/git2/refspec.h | 13 ++++++++++++- src/refspec.c | 24 +++++++++++++++++------- tests-clar/network/remotes.c | 11 +++++++++-- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/git2/refspec.h b/include/git2/refspec.h index 3e83e41e2..ec7830b7c 100644 --- a/include/git2/refspec.h +++ b/include/git2/refspec.h @@ -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 diff --git a/src/refspec.c b/src/refspec.c index 4f324d3c1..a51b0cfab 100644 --- a/src/refspec.c +++ b/src/refspec.c @@ -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) diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c index b138d8c10..51d6c946f 100644 --- a/tests-clar/network/remotes.c +++ b/tests-clar/network/remotes.c @@ -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; -- 2.39.5