Add git_refspec_transform Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
diff --git a/include/git2/refspec.h b/include/git2/refspec.h
index 8523d5a..0cbe42f 100644
--- a/include/git2/refspec.h
+++ b/include/git2/refspec.h
@@ -29,4 +29,14 @@ const char *git_refspec_dst(const git_refspec *refspec);
*/
int git_refspec_src_match(const git_refspec *refspec, const char *refname);
+/**
+ * Transform a reference to its target following the refspec's rules
+ *
+ * @param out where to store the target name
+ * @param in the source reference
+ * @param spec the refspec
+ * @param len the length of the out buffer
+ * @preturn GIT_SUCCESS, GIT_ESHORTBUFFER or another error
+ */
+int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name);
#endif
diff --git a/src/refspec.c b/src/refspec.c
index 38cbb05..8500e07 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -23,6 +23,8 @@
* Boston, MA 02110-1301, USA.
*/
+#include "git2/errors.h"
+
#include "common.h"
#include "refspec.h"
#include "util.h"
@@ -70,3 +72,37 @@ int git_refspec_src_match(const git_refspec *refspec, const char *refname)
{
return git__fnmatch(refspec->src, refname, 0);
}
+
+int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name)
+{
+ size_t baselen, namelen;
+
+ baselen = strlen(spec->dst);
+ if (outlen <= baselen)
+ return git__throw(GIT_EINVALIDREFNAME, "Reference name too long");
+
+ /*
+ * 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' */
+ return GIT_SUCCESS;
+ }
+
+ /* There's a '*' at the end, so remove its length */
+ baselen--;
+
+ /* skip the prefix, -1 is for the '*' */
+ name += strlen(spec->src) - 1;
+
+ namelen = strlen(name);
+
+ if (outlen <= baselen + namelen)
+ return git__throw(GIT_EINVALIDREFNAME, "Reference name too long");
+
+ memcpy(out, spec->dst, baselen);
+ memcpy(out + baselen, name, namelen + 1);
+
+ return GIT_SUCCESS;
+}