summaryrefslogtreecommitdiff
path: root/src/refspec.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-09-07 17:53:49 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2021-10-17 09:49:01 -0400
commitf0e693b18afbe1de37d7da5b5a8967b6c87d8e53 (patch)
treebe5e1cdbfa218ba81ec06bf45e45cfeb7f79a2a5 /src/refspec.c
parent5346be3ddd3bcf19779c5d62e71f8442a0171133 (diff)
downloadlibgit2-ethomson/gitstr.tar.gz
str: introduce `git_str` for internal, `git_buf` is externalethomson/gitstr
libgit2 has two distinct requirements that were previously solved by `git_buf`. We require: 1. A general purpose string class that provides a number of utility APIs for manipulating data (eg, concatenating, truncating, etc). 2. A structure that we can use to return strings to callers that they can take ownership of. By using a single class (`git_buf`) for both of these purposes, we have confused the API to the point that refactorings are difficult and reasoning about correctness is also difficult. Move the utility class `git_buf` to be called `git_str`: this represents its general purpose, as an internal string buffer class. The name also is an homage to Junio Hamano ("gitstr"). The public API remains `git_buf`, and has a much smaller footprint. It is generally only used as an "out" param with strict requirements that follow the documentation. (Exceptions exist for some legacy APIs to avoid breaking callers unnecessarily.) Utility functions exist to convert a user-specified `git_buf` to a `git_str` so that we can call internal functions, then converting it back again.
Diffstat (limited to 'src/refspec.c')
-rw-r--r--src/refspec.c69
1 files changed, 32 insertions, 37 deletions
diff --git a/src/refspec.c b/src/refspec.c
index c72721a43..f0a0c2bfb 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -7,8 +7,7 @@
#include "refspec.h"
-#include "git2/errors.h"
-
+#include "buf.h"
#include "refs.h"
#include "util.h"
#include "vector.h"
@@ -243,16 +242,12 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
}
static int refspec_transform(
- git_buf *out, const char *from, const char *to, const char *name)
+ git_str *out, const char *from, const char *to, const char *name)
{
const char *from_star, *to_star;
size_t replacement_len, star_offset;
- int error;
-
- if ((error = git_buf_sanitize(out)) < 0)
- return error;
- git_buf_clear(out);
+ git_str_clear(out);
/*
* There are two parts to each side of a refspec, the bit
@@ -269,72 +264,72 @@ static int refspec_transform(
star_offset = from_star - from;
/* the first half is copied over */
- git_buf_put(out, to, to_star - to);
+ git_str_put(out, to, to_star - to);
/*
* Copy over the name, but exclude the trailing part in "from" starting
* after the glob
*/
replacement_len = strlen(name + star_offset) - strlen(from_star + 1);
- git_buf_put(out, name + star_offset, replacement_len);
+ git_str_put(out, name + star_offset, replacement_len);
- return git_buf_puts(out, to_star + 1);
+ return git_str_puts(out, to_star + 1);
}
int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
{
- int error;
+ GIT_BUF_WRAP_PRIVATE(out, git_refspec__transform, spec, name);
+}
+int git_refspec__transform(git_str *out, const git_refspec *spec, const char *name)
+{
GIT_ASSERT_ARG(out);
GIT_ASSERT_ARG(spec);
GIT_ASSERT_ARG(name);
- if ((error = git_buf_sanitize(out)) < 0)
- return error;
-
if (!git_refspec_src_matches(spec, name)) {
git_error_set(GIT_ERROR_INVALID, "ref '%s' doesn't match the source", name);
return -1;
}
if (!spec->pattern)
- return git_buf_puts(out, spec->dst ? spec->dst : "");
+ return git_str_puts(out, spec->dst ? spec->dst : "");
return refspec_transform(out, spec->src, spec->dst, name);
}
int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
{
- int error;
+ GIT_BUF_WRAP_PRIVATE(out, git_refspec__rtransform, spec, name);
+}
+int git_refspec__rtransform(git_str *out, const git_refspec *spec, const char *name)
+{
GIT_ASSERT_ARG(out);
GIT_ASSERT_ARG(spec);
GIT_ASSERT_ARG(name);
- if ((error = git_buf_sanitize(out)) < 0)
- return error;
-
if (!git_refspec_dst_matches(spec, name)) {
git_error_set(GIT_ERROR_INVALID, "ref '%s' doesn't match the destination", name);
return -1;
}
if (!spec->pattern)
- return git_buf_puts(out, spec->src);
+ return git_str_puts(out, spec->src);
return refspec_transform(out, spec->dst, spec->src, name);
}
-int git_refspec__serialize(git_buf *out, const git_refspec *refspec)
+int git_refspec__serialize(git_str *out, const git_refspec *refspec)
{
if (refspec->force)
- git_buf_putc(out, '+');
+ git_str_putc(out, '+');
- git_buf_printf(out, "%s:%s",
+ git_str_printf(out, "%s:%s",
refspec->src != NULL ? refspec->src : "",
refspec->dst != NULL ? refspec->dst : "");
- return git_buf_oom(out) == false;
+ return git_str_oom(out) == false;
}
int git_refspec_is_wildcard(const git_refspec *spec)
@@ -354,7 +349,7 @@ git_direction git_refspec_direction(const git_refspec *spec)
int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
{
- git_buf buf = GIT_BUF_INIT;
+ git_str buf = GIT_STR_INIT;
size_t j, pos;
git_remote_head key;
git_refspec *cur;
@@ -382,14 +377,14 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
/* shorthand on the lhs */
if (git__prefixcmp(spec->src, GIT_REFS_DIR)) {
for (j = 0; formatters[j]; j++) {
- git_buf_clear(&buf);
- git_buf_printf(&buf, formatters[j], spec->src);
- GIT_ERROR_CHECK_ALLOC_BUF(&buf);
+ git_str_clear(&buf);
+ git_str_printf(&buf, formatters[j], spec->src);
+ GIT_ERROR_CHECK_ALLOC_STR(&buf);
- key.name = (char *) git_buf_cstr(&buf);
+ key.name = (char *) git_str_cstr(&buf);
if (!git_vector_search(&pos, refs, &key)) {
/* we found something to match the shorthand, set src to that */
- cur->src = git_buf_detach(&buf);
+ cur->src = git_str_detach(&buf);
}
}
}
@@ -403,18 +398,18 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
if (spec->dst && git__prefixcmp(spec->dst, GIT_REFS_DIR)) {
/* if it starts with "remotes" then we just prepend "refs/" */
if (!git__prefixcmp(spec->dst, "remotes/")) {
- git_buf_puts(&buf, GIT_REFS_DIR);
+ git_str_puts(&buf, GIT_REFS_DIR);
} else {
- git_buf_puts(&buf, GIT_REFS_HEADS_DIR);
+ git_str_puts(&buf, GIT_REFS_HEADS_DIR);
}
- git_buf_puts(&buf, spec->dst);
- GIT_ERROR_CHECK_ALLOC_BUF(&buf);
+ git_str_puts(&buf, spec->dst);
+ GIT_ERROR_CHECK_ALLOC_STR(&buf);
- cur->dst = git_buf_detach(&buf);
+ cur->dst = git_str_detach(&buf);
}
- git_buf_dispose(&buf);
+ git_str_dispose(&buf);
if (cur->dst == NULL && spec->dst != NULL) {
cur->dst = git__strdup(spec->dst);