Commit bf522e08114a4dc25815b09db201266a0791381c

Carlos Martín Nieto 2014-01-26T16:59:36

refspec: move to git_buf for outputting strings

diff --git a/include/git2/refspec.h b/include/git2/refspec.h
index d96b83c..9acdc72 100644
--- a/include/git2/refspec.h
+++ b/include/git2/refspec.h
@@ -10,6 +10,7 @@
 #include "common.h"
 #include "types.h"
 #include "net.h"
+#include "buffer.h"
 
 /**
  * @file git2/refspec.h
@@ -82,23 +83,21 @@ GIT_EXTERN(int) git_refspec_dst_matches(const git_refspec *refspec, const char *
  * Transform a reference to its target following the refspec's rules
  *
  * @param out where to store the target 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_transform(char *out, size_t outlen, const git_refspec *spec, const char *name);
+GIT_EXTERN(int) git_refspec_transform(git_buf *out, 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_EXTERN(int) git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name);
 
 GIT_END_DECL
 
diff --git a/src/branch.c b/src/branch.c
index a702c66..a1a04b2 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -329,7 +329,7 @@ int git_branch_upstream_name(
 			goto cleanup;
 		}
 
-		if (git_refspec_transform_r(&buf, refspec, merge_name) < 0)
+		if (git_refspec_transform(&buf, refspec, merge_name) < 0)
 			goto cleanup;
 	} else
 		if (git_buf_sets(&buf, merge_name) < 0)
@@ -520,7 +520,7 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
 
 		fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
 		git_buf_clear(&value);
-		if (!fetchspec || git_refspec_transform_l(&value, fetchspec, git_reference_name(upstream)) < 0)
+		if (!fetchspec || git_refspec_rtransform(&value, fetchspec, git_reference_name(upstream)) < 0)
 			goto on_error;
 
 		git_remote_free(remote);
diff --git a/src/clone.c b/src/clone.c
index 828c47f..2e9d72a 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -131,7 +131,7 @@ static int reference_matches_remote_head(
 
 	if (!error && !git_oid__cmp(&head_info->remote_head_oid, &oid)) {
 		/* Determine the local reference name from the remote tracking one */
-		error = git_refspec_transform_l(
+		error = git_refspec_rtransform(
 			&head_info->branchname, head_info->refspec, reference_name);
 
 		if (!error &&
@@ -199,7 +199,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
 	}
 
 	/* Determine the remote tracking reference name from the local master */
-	if ((error = git_refspec_transform_r(
+	if ((error = git_refspec_transform(
 		&remote_master_name,
 		head_info.refspec,
 		GIT_REFS_HEADS_MASTER_FILE)) < 0)
diff --git a/src/push.c b/src/push.c
index 0be82f3..d39a271 100644
--- a/src/push.c
+++ b/src/push.c
@@ -214,7 +214,7 @@ int git_push_update_tips(git_push *push)
 		if (!fetch_spec)
 			continue;
 
-		if ((error = git_refspec_transform_r(&remote_ref_name, fetch_spec, status->ref)) < 0)
+		if ((error = git_refspec_transform(&remote_ref_name, fetch_spec, status->ref)) < 0)
 			goto on_error;
 
 		/* Find matching  push ref spec */
diff --git a/src/refspec.c b/src/refspec.c
index a973400..fa60aa7 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -178,54 +178,6 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
 	return (p_fnmatch(refspec->dst, refname, 0) == 0);
 }
 
-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(to);
-	if (outlen <= baselen) {
-		giterr_set(GITERR_INVALID, "Reference name too long");
-		return GIT_EBUFS;
-	}
-
-	/*
-	 * No '*' at the end means that it's mapped to one specific local
-	 * branch, so no actual transformation is needed.
-	 */
-	if (to[baselen - 1] != '*') {
-		memcpy(out, to, baselen + 1); /* include '\0' */
-		return 0;
-	}
-
-	/* There's a '*' at the end, so remove its length */
-	baselen--;
-
-	/* skip the prefix, -1 is for the '*' */
-	name += strlen(from) - 1;
-
-	namelen = strlen(name);
-
-	if (outlen <= baselen + namelen) {
-		giterr_set(GITERR_INVALID, "Reference name too long");
-		return GIT_EBUFS;
-	}
-
-	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)
 {
@@ -233,6 +185,8 @@ static int refspec_transform(
 	size_t from_len = from ? strlen(from) : 0;
 	size_t name_len = name ? strlen(name) : 0;
 
+	git_buf_sanitize(out);
+
 	if (git_buf_set(out, to, to_len) < 0)
 		return -1;
 
@@ -253,12 +207,12 @@ static int refspec_transform(
 	return git_buf_put(out, name + from_len, name_len - from_len);
 }
 
-int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name)
+int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
 {
 	return refspec_transform(out, spec->src, spec->dst, name);
 }
 
-int git_refspec_transform_l(git_buf *out, const git_refspec *spec, const char *name)
+int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
 {
 	return refspec_transform(out, spec->dst, spec->src, name);
 }
diff --git a/src/refspec.h b/src/refspec.h
index 51b7bfe..375465f 100644
--- a/src/refspec.h
+++ b/src/refspec.h
@@ -31,28 +31,6 @@ int git_refspec__parse(
 
 void git_refspec__free(git_refspec *refspec);
 
-/**
- * Transform a reference to its target following the refspec's rules,
- * and writes the results into a git_buf.
- *
- * @param out where to store the target name
- * @param spec the refspec
- * @param name the name of the reference to transform
- * @return 0 or error if buffer allocation fails
- */
-int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name);
-
-/**
- * Transform a reference from its target following the refspec's rules,
- * and writes the results into a git_buf.
- *
- * @param out where to store the source name
- * @param spec the refspec
- * @param name the name of the reference to transform
- * @return 0 or error if buffer allocation fails
- */
-int git_refspec_transform_l(git_buf *out, const git_refspec *spec, const char *name);
-
 int git_refspec__serialize(git_buf *out, const git_refspec *refspec);
 
 /**
diff --git a/src/remote.c b/src/remote.c
index 5b3656a..5d35aff 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -896,7 +896,7 @@ static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vec
 	if ((error = git_reference_resolve(&resolved_ref, ref)) < 0 ||
 		(!git_reference_is_branch(resolved_ref)) ||
 		(error = git_branch_upstream(&tracking_ref, resolved_ref)) < 0 ||
-		(error = git_refspec_transform_l(&remote_name, spec, git_reference_name(tracking_ref))) < 0) {
+		(error = git_refspec_rtransform(&remote_name, spec, git_reference_name(tracking_ref))) < 0) {
 		/* Not an error if HEAD is unborn or no tracking branch */
 		if (error == GIT_ENOTFOUND)
 			error = 0;
@@ -1011,7 +1011,7 @@ static int update_tips_for_spec(git_remote *remote, git_refspec *spec, git_vecto
 			continue;
 
 		if (git_refspec_src_matches(spec, head->name) && spec->dst) {
-			if (git_refspec_transform_r(&refname, spec, head->name) < 0)
+			if (git_refspec_transform(&refname, spec, head->name) < 0)
 				goto on_error;
 		} else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
 
diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c
index 44a98d3..09963e8 100644
--- a/tests/network/remote/remotes.c
+++ b/tests/network/remote/remotes.c
@@ -230,27 +230,20 @@ void test_network_remote_remotes__fnmatch(void)
 
 void test_network_remote_remotes__transform(void)
 {
-	char ref[1024] = {0};
+	git_buf ref = GIT_BUF_INIT;
 
-	cl_git_pass(git_refspec_transform(ref, sizeof(ref), _refspec, "refs/heads/master"));
+	cl_git_pass(git_refspec_transform(&ref, _refspec, "refs/heads/master"));
 	cl_assert_equal_s(ref, "refs/remotes/test/master");
+	git_buf_free(&ref);
 }
 
 void test_network_remote_remotes__transform_destination_to_source(void)
 {
-	char ref[1024] = {0};
+	git_buf ref = GIT_BUF_INIT;
 
-	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_remote_remotes__transform_r(void)
-{
-	git_buf buf = GIT_BUF_INIT;
-
-	cl_git_pass(git_refspec_transform_r(&buf,  _refspec, "refs/heads/master"));
-	cl_assert_equal_s(git_buf_cstr(&buf), "refs/remotes/test/master");
-	git_buf_free(&buf);
+	cl_git_pass(git_refspec_rtransform(&ref, _refspec, "refs/remotes/test/master"));
+	cl_assert_equal_s(ref.ptr, "refs/heads/master");
+	git_buf_free(&ref);
 }
 
 void test_network_remote_remotes__missing_refspecs(void)
diff --git a/tests/online/push.c b/tests/online/push.c
index 33f1746..8efe21e 100644
--- a/tests/online/push.c
+++ b/tests/online/push.c
@@ -219,7 +219,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r
 		if (!fetch_spec)
 			continue;
 
-		cl_git_pass(git_refspec_transform_r(&ref_name, fetch_spec, expected_refs[i].name));
+		cl_git_pass(git_refspec_transform(&ref_name, fetch_spec, expected_refs[i].name));
 
 		/* Find matching remote branch */
 		git_vector_foreach(&actual_refs, j, actual_ref) {