Commit bf522e08 by Carlos Martín Nieto

refspec: move to git_buf for outputting strings

parent e1d7f003
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "common.h" #include "common.h"
#include "types.h" #include "types.h"
#include "net.h" #include "net.h"
#include "buffer.h"
/** /**
* @file git2/refspec.h * @file git2/refspec.h
...@@ -82,23 +83,21 @@ GIT_EXTERN(int) git_refspec_dst_matches(const git_refspec *refspec, const char * ...@@ -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 * Transform a reference to its target following the refspec's rules
* *
* @param out where to store the target name * @param out where to store the target name
* @param outlen the size of the `out` buffer
* @param spec the refspec * @param spec the refspec
* @param name the name of the reference to transform * @param name the name of the reference to transform
* @return 0, GIT_EBUFS or another error * @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 * Transform a target reference to its source reference following the refspec's rules
* *
* @param out where to store the source reference name * @param out where to store the source reference name
* @param outlen the size of the `out` buffer
* @param spec the refspec * @param spec the refspec
* @param name the name of the reference to transform * @param name the name of the reference to transform
* @return 0, GIT_EBUFS or another error * @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 GIT_END_DECL
......
...@@ -329,7 +329,7 @@ int git_branch_upstream_name( ...@@ -329,7 +329,7 @@ int git_branch_upstream_name(
goto cleanup; goto cleanup;
} }
if (git_refspec_transform_r(&buf, refspec, merge_name) < 0) if (git_refspec_transform(&buf, refspec, merge_name) < 0)
goto cleanup; goto cleanup;
} else } else
if (git_buf_sets(&buf, merge_name) < 0) if (git_buf_sets(&buf, merge_name) < 0)
...@@ -520,7 +520,7 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name) ...@@ -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)); fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
git_buf_clear(&value); 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; goto on_error;
git_remote_free(remote); git_remote_free(remote);
......
...@@ -131,7 +131,7 @@ static int reference_matches_remote_head( ...@@ -131,7 +131,7 @@ static int reference_matches_remote_head(
if (!error && !git_oid__cmp(&head_info->remote_head_oid, &oid)) { if (!error && !git_oid__cmp(&head_info->remote_head_oid, &oid)) {
/* Determine the local reference name from the remote tracking one */ /* 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); &head_info->branchname, head_info->refspec, reference_name);
if (!error && if (!error &&
...@@ -199,7 +199,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) ...@@ -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 */ /* Determine the remote tracking reference name from the local master */
if ((error = git_refspec_transform_r( if ((error = git_refspec_transform(
&remote_master_name, &remote_master_name,
head_info.refspec, head_info.refspec,
GIT_REFS_HEADS_MASTER_FILE)) < 0) GIT_REFS_HEADS_MASTER_FILE)) < 0)
......
...@@ -214,7 +214,7 @@ int git_push_update_tips(git_push *push) ...@@ -214,7 +214,7 @@ int git_push_update_tips(git_push *push)
if (!fetch_spec) if (!fetch_spec)
continue; 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; goto on_error;
/* Find matching push ref spec */ /* Find matching push ref spec */
......
...@@ -178,54 +178,6 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname) ...@@ -178,54 +178,6 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
return (p_fnmatch(refspec->dst, refname, 0) == 0); 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( static int refspec_transform(
git_buf *out, const char *from, const char *to, const char *name) git_buf *out, const char *from, const char *to, const char *name)
{ {
...@@ -233,6 +185,8 @@ static int refspec_transform( ...@@ -233,6 +185,8 @@ static int refspec_transform(
size_t from_len = from ? strlen(from) : 0; size_t from_len = from ? strlen(from) : 0;
size_t name_len = name ? strlen(name) : 0; size_t name_len = name ? strlen(name) : 0;
git_buf_sanitize(out);
if (git_buf_set(out, to, to_len) < 0) if (git_buf_set(out, to, to_len) < 0)
return -1; return -1;
...@@ -253,12 +207,12 @@ static int refspec_transform( ...@@ -253,12 +207,12 @@ static int refspec_transform(
return git_buf_put(out, name + from_len, name_len - from_len); 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); 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); return refspec_transform(out, spec->dst, spec->src, name);
} }
......
...@@ -31,28 +31,6 @@ int git_refspec__parse( ...@@ -31,28 +31,6 @@ int git_refspec__parse(
void git_refspec__free(git_refspec *refspec); 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); int git_refspec__serialize(git_buf *out, const git_refspec *refspec);
/** /**
......
...@@ -896,7 +896,7 @@ static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vec ...@@ -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 || if ((error = git_reference_resolve(&resolved_ref, ref)) < 0 ||
(!git_reference_is_branch(resolved_ref)) || (!git_reference_is_branch(resolved_ref)) ||
(error = git_branch_upstream(&tracking_ref, resolved_ref)) < 0 || (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 */ /* Not an error if HEAD is unborn or no tracking branch */
if (error == GIT_ENOTFOUND) if (error == GIT_ENOTFOUND)
error = 0; error = 0;
...@@ -1011,7 +1011,7 @@ static int update_tips_for_spec(git_remote *remote, git_refspec *spec, git_vecto ...@@ -1011,7 +1011,7 @@ static int update_tips_for_spec(git_remote *remote, git_refspec *spec, git_vecto
continue; continue;
if (git_refspec_src_matches(spec, head->name) && spec->dst) { 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; goto on_error;
} else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) { } else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
......
...@@ -230,27 +230,20 @@ void test_network_remote_remotes__fnmatch(void) ...@@ -230,27 +230,20 @@ void test_network_remote_remotes__fnmatch(void)
void test_network_remote_remotes__transform(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"); cl_assert_equal_s(ref, "refs/remotes/test/master");
git_buf_free(&ref);
} }
void test_network_remote_remotes__transform_destination_to_source(void) 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_git_pass(git_refspec_rtransform(&ref, _refspec, "refs/remotes/test/master"));
cl_assert_equal_s(ref, "refs/heads/master"); cl_assert_equal_s(ref.ptr, "refs/heads/master");
} git_buf_free(&ref);
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);
} }
void test_network_remote_remotes__missing_refspecs(void) void test_network_remote_remotes__missing_refspecs(void)
......
...@@ -219,7 +219,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r ...@@ -219,7 +219,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r
if (!fetch_spec) if (!fetch_spec)
continue; 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 */ /* Find matching remote branch */
git_vector_foreach(&actual_refs, j, actual_ref) { git_vector_foreach(&actual_refs, j, actual_ref) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment